<?php
namespace control;

/*
*物料档案类
*/

class materialClass extends adIndexClass
{
    private const page = 'material'; # 权限
    private const table = 'material'; # 数据表
    private const title = '物料档案';
    public const defaultName = '默认属性';
    public array $checkOption = ['产成品', '半成品', '原材料'];
    public array $sourceOption = ['采购', '自制', '委外', '虚拟'];
    public array $controlOption = ['允许采购', '允许销售', '允许库存', '允许生产', '允许委外'];

    //组合物料分类树形结构
    public static function storageMaterialType($data = []): array
    {
        // 条件
        $data['where'] = $data['where'] ?? "pid='0' and coid = '" . self::$coid . "'";
        //当前层级
        $data['level'] = isset($data['level']) ? $data['level'] + 1 : 0;
        // 结果
        $result = find(['table' => 'material_type', 'field' => 'id,name', 'where' => $data['where'] . " and coid = '" . self::$coid . "' order by list asc,time asc"]);
        $temp   = [];
        if ($result['array']) {
            foreach ($result['array'] as $value) {
                // 判断下级是否存在
                $data['where'] = " pid='{$value['id']}' and coid = '" . self::$coid . "' ";
                $has           = query('material_type', $data['where']);
                $category = array(
                    'name' => $value['name'],
                    'level' => $data['level'],
                    'where' => $data['where'],
                    'children' => $has['id']?self::storageMaterialType($data):array()
                );
                $temp[$value['id']] = $category;
            }
        }
        return $temp;
    }
    // 获取左侧分类数据
    public static function getSidebarData($click = '', $key='materialType', $reset = false): string
    {
        $click = $click?:'replaceContent(this, \'material\')';
        $data = self::rGet($key.self::$coid);

        if(!empty($data) && !$reset && strlen($data) > 60){
            return $data;
        }else{
            $sidebarArr = self::storageMaterialType();
            $data = self::getDepartmentAll($sidebarArr, 0, '',  $click);
            self::$redis->set(redisKey . $key.self::$coid, $data);
            return $data;
        }

    }

    public static function getDepartmentAll($typeArr, $level, $where = '', $click = ''): string
    {
        // 点击事件
        $data['click'] = $click ?? "replaceDetail(this,'" . self::page . "')";
        //当前层级
        $data['level'] = $level?:0;
        $data['where'] = $where ?: " pid='0' and coid = '" . self::$coid . "' ";
        // 结果
        $style = $data['level'] == 0 ? '' : " class='child-node' data-level='{$data['level']}' ";
        $temp = "<ul {$style} {$data['where']}>";
        if ($typeArr) {
            foreach ($typeArr as $id=>$value) {
                // 角标
                $arrow = "<span class='arrow'  onclick=\"liZoom($(this).parent())\"></span>";
                // 操作按钮
                $dots = "<div class='actionBlock none'>
                            <img data-pid='{$id}' title='" . lang('material.getDepartmentAll.addSub') . "' onclick=\"layer('" . self::page . "','catalog',{id:'" . suiji() . "',pid:'{$id}'})\" src='".root."img/control/list_add.svg'>
                            <img data-id='{$id}' title='" . lang('material.getDepartmentAll.edit') . "' onclick=\"layer('" . self::page . "','catalog',{id:'" . $id . "'})\" src='".root."img/control/edit.svg'>
                            <img data-id='{$id}' title='" . lang('material.getDepartmentAll.del') . "' onclick=\"layer('" . self::page . "','operate',{'act': 'delType',id:'" . $id . "'})\" src='".root."img/control/list_del.svg'>
                        </div>";
                if ($value['children']) {
                    $temp .= "<li class='arrow-li' data-id='{$id}' onclick=\"{$data['click']}\">
                                {$arrow}
                                <span class='textcontent' title='{$value['name']}'>
                                    <span class='textcontent_ico'></span>
                                    {$value['name']}
                                </span>
                                <div class='action-div'>{$dots}</div>
                            </li>";
                    $temp .= self::getDepartmentAll($value['children'], $data['level']+1, $value['where'], $data['click']);
                } else {
                    $temp .= "<li class='arrow-no-li'  data-id='{$id}' onclick=\"{$data['click']}\">
                                <span class='textcontent' title='{$value['name']}'>
                                    <span class='textcontent_ico'></span>
                                    {$value['name']}
                                </span>
                                <div class='action-div'>{$dots}</div>
                            </li>";
                }
            }
        }
        $temp .= '</ul>';
        return $temp;
    }

    /**
     * 异步加载
     *
     */
    public function homeRightJson(): bool|string
    {
        $json['html'] = $this->homeRight();
        return json_encode($json, 320);
    }

    public function homeRightJsonSearch(): bool|string
    {
        return $this->homeSearch();
    }

    /**
     * 左侧搜索框
     *
     * @return string
     */
    public function getContainerLeftJson(): string
    {
        $click = 'replaceContent(this, \'material\')';
        $json['html'] = self::getSidebarData(click:$click);
        return json_encode($json, 320);
    }


    public function homeHtml(): string
    {
        //返回
        $rightHtml = $this->homeRight();
        $searchvalue = $_SESSION[self::page]['keyword'] ?? '';
        $click = 'replaceContent(this, \'material\')';
        $all = self::getSidebarData(click:$click);
        return componentClass::leftNav([
            'searchvalue'=>$searchvalue,
            'title'=>'搜索分类',
            'inputOther'=>" onblur=\"typeSession(this,'material','".self::page."')\" ",
            'click'=>$click,
            'edit'=>1,
            'allTitle'=>'全部分类',
            'button'=>"<img class='tool-img' title='添加分类' onclick=\"layer('" . self::page . "','catalog',{id:'" . suiji() . "', pid: 0})\" src='".root."img/control/list_add.svg'>",
            'all'=>$all,
            'rightHtml'=>$rightHtml,
        ]);
    }

    /*列表页-查询条件*/
    public function home()
    {
        //返回
        return $this->homeFun($this->homeHtml());
    }

    public function catalog(): bool|string
    {
        //数据查询
        $info = query(self::table . '_type', " id = '" . $this->post('id') . "' ");
        $pid = $info['pid'] ?: ($this->post('pid') ?: '0');
        //表单
        $html = $this->layerEdit([
            "table" => [
                [
                    must . lang('material.catalog.type') . "：" => text(["name" => "name", "value" => $info['name'] ?? null, 'class' => 'text']),
                ],
                [
                    lang('material.catalog.list') . "：" => text(["name" => "list", "value" => $info['list'] ?? null, 'class' => 'text']) . hidden(['name' => 'pid', 'value' => $pid]),
                ]
            ]
        ]);
        //返回
        return $this->layer(["title" => lang('material.catalog.edit'), "height" => 220, "html" => $html]);
    }

    public function catalogEdit(): bool|string
    {
        //赋值
        $field = [
            'pid' => $this->post('pid') ?: '0',
            "name" => $this->post('name'),      //部门名称
            "list" => $this->post('list'),      //排序号
        ];
        $info = query(self::table . '_type', " id = '" . $this->post('id') . "' ");
        //判断
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = lang('material.catalogEdit.power');
        } elseif (empty($field['name'])) {
            $json['warn'] = lang('material.catalogEdit.name');
        } elseif (sqlNum(self::table . '_type', "pid = '$field[pid]' and coid ='" . self::$coid . "' and name = '$field[name]' and id != '" . $this->post('id') . "' ") > 0) {
            $json['warn'] = lang('material.catalogEdit.repeat');
        } elseif (empty($this->post('id'))) {
            $json['warn'] = lang('material.catalogEdit.idEmpty');
        } elseif (empty($info['id'])) {
            $field = array_merge($field, ["id" => $this->post('id'), 'coid' => self::$coid, "time" => $this->time]);
            $json['warn'] = insert(["table" => self::table . '_type', "field" => $field]);
        } else {
            $json['warn'] = update(["table" => self::table . '_type', "field" => $field, "where" => "id = '" . $this->post('id') . "'"]);
        }
        if (in_array($json['warn'], array("新增成功", "更新成功"))) {
            self::getSidebarData(reset: true); //重置左侧分类导航栏
            //添加日志
            $type = mb_substr($json['warn'], 0, 2, 'utf-8');
            $text = str_replace(['{{staffName}}', '{{type}}', '{{name}}'], [$this->control['name'], $type, $field['name']], lang('material.catalogEdit.log'));
            $this->logText(array("type" => self::page, "text" => $text));
            //提示
            $_SESSION['warn'] = $json['warn'];
            $json['warn'] = 2;
        }
        //返回
        return json_encode($json, 320);
    }

    /**
     * 字段初始化
     */
    public function fieldInit($fun): array
    {
        switch ($fun) {
            default:
                $tr = [
                    'typeName'          => [
                        'name'  => '{l.material.homeSearch.type}',
                        'width' => 100,
                    ],
                    'code' => [
                        'name'  => "{l.material.homeSearch.code}",
                        'width' => 150,
                        'sort' => 1,
                    ],
                    'name'  => [
                        'name'  => "{l.material.homeSearch.name}",
                        'width' => 150,
                    ],
                    'model'  => [
                        'name'  => '{l.material.homeSearch.model}',
                        'width' => 150,
                    ],
                    'unit'  => [
                        'name'  => '{l.material.homeSearch.unit}',
                        'width' => 60,
                    ],
                    'bomNum'         => [
                        'name'  => '{l.material.homeSearch.isBom}',
                        'width' => 120,
                    ],
                    'quarantineNum'          => [
                        'name'  => '{l.material.homeSearch.isQuarantine}',
                        'width' => 120,
                    ],
                    'routingNum'          => [
                        'name'  => '{l.material.homeSearch.isRouting}',
                        'width' => 120,
                    ],
                    'text'          => [
                        'name'  => '{l.material.edit.text}',
                        'width' => 150,
                    ],
                    'state'          => [
                        'name'  => '{l.material.homeSearch.state}',
                        'width' => 100,
                    ]
                ];
        }
        return $tr;
    }

    /*列表页-查询条件*/
    public function homeOptions($isAsync = true)
    {
        $typeId = $this->post('objId') ?? null;
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    L('material.searchHtml.code') => text(array("name" => "code")).
                        hidden(array('name' => 'typeId', 'value' => $typeId)),
                    L('material.searchHtml.materialName')   => text(array("name" => "materialName")),
                    L('material.searchHtml.model') => text(array("name" => "model")),
                ],
                [
                    L('material.searchHtml.isBom')  => select(array("name" => "isBom", "option" => [1 => '否', 2 => '是'])),
                    L('material.searchHtml.isQuarantine') => select(array("name" => "isQuarantine", "option" => [1 => '否', 2 => '是'])),
                    L('material.searchHtml.isRouting') => select(array("name" => "isRouting", "option" => [1 => '否', 2 => '是'])),
                ],
                [
                    L('material.searchHtml.state') => select(["name" => "state", 'option' => ['启用', '停用']]),
                ]
            ]
        ],1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }

    public function homeRight()
    {
        $typeId = $this->post('objId') ?? null;
        $html = $this->homeOptions(false);
        //控件
        $button = "";
        $url = root . "control/adIndex.html?cla=" . self::page;
        $editPower = $this->power(self::page, "edit");
        if ($editPower && $typeId) {
            $button .= "<span onclick=\"newIframe('" . lang('material.homeSearch.materialDetail') . "','" . $url . "&fun=edit&typeId={$typeId}')\" class='spanButton'>" . lang('material.homeSearch.new') . "</span>\n";
        }
        if ($this->power(self::page, "del")) {
            $button .= "<span class='spanButton' onclick=\"layer('" . self::page . "', 'operate', {'act': 'del'})\">" . lang('material.homeSearch.del') . "</span>\n";
        }
        if ($this->power(self::page, 'import')) {
            $button .="<span class='spanButton' onclick=\"layer('importTemplate','importFrame',{cla:'".self::page."'})\">导入</span>";
        }
        if ($this->power(self::page, "export")) {
            $button .="<span class='spanButton' onclick=\"layer('importTemplate','exportFrame',{cla:'".self::page."'})\">导出</span>";
        }
        if ($this->power(self::page, "edit")) {
            $button .= "<span onclick=\"layer('" . self::page . "','stateSwitch',{type:'启用'})\" class='spanButton'>" . lang('material.homeSearch.enable') . "</span>\n";
            $button .= "<span onclick=\"layer('" . self::page . "','stateSwitch',{type:'停用'})\" class='spanButton'>" . lang('material.homeSearch.stop') . "</span>\n";
            $button .= "<span onclick=\"layer('" . self::page . "','settingSubject',{})\" class='spanButton'>指定科目</span>\n";
        }
        //返回
        return $this->search($html, layout: 'pop', toolButton: $button);
    }

    public function homeSearch(): bool|string
    {
        $typeId = $this->post('typeId');
        $like = array(
            "name" => $this->post('materialName'),//名称
            "code" => $this->post('code'),//所在位置
            "model" => $this->post('model'),//规格型号
            "typePath" => $this->post('typeId'),//分类
        );
        //全等查询数组
        $equal = array(
            "state" => $this->post('state'),//状态
        );
        $and = " and coid = '" . self::$coid . "'";
        if ($this->post('createTime')) {
            $and .= self::timeComparison($this->post('time'));
        }
        if ($this->post('isBom')) {
            $str = $this->post('isBom') == 1 ? " = 0 " : " > 0 ";
            $and .= " and (select ifnull(count(id),0) from bom where coid = '" . self::$coid . "' and state = '启用' and materialId = material.id ) " . $str;
        }
        if ($this->post('isQuarantine')) {
            $str = $this->post('isQuarantine') == 1 ? " = 0 " : " > 0 ";
            $and .= " and (select ifnull(count(id),0) from quarantine where state = '启用' and materialId = material.id) " . $str;
        }
        if ($this->post('isRouting')) {
            $str = $this->post('isRouting') == 1 ? " = 0 " : " > 0 ";
            $and .= " and (select ifnull(count(id),0) from routing where state = '启用' and materialId = material.id) " . $str;
        }

        //获取查询结果
        $where = search(array("like" => $like, "=" => $equal)) . $and;
        //排序
        $orderBy = $this->listSort(array(
            "search"  => $this->post('list_sort_key') ?: 'time',
            "sort" => $this->post('list_sort') ?: "desc",
            "array"   => array(),
        ));
        $page = $this->page(array(
            "table" => self::table,
            "field" => "*,
            (select ifnull(count(id),0) from bom where coid = '" . self::$coid . "' and state = '启用' and materialId = material.id ) as bomNum,
            (select ifnull(count(id),0) from quarantine where state = '启用' and materialId = material.id ) as quarantineNum,
            (select ifnull(count(id),0) from routing where state = '启用' and materialId = material.id ) as routingNum",
            "where" => $where,
            "order" => $orderBy['orderBy']
        ));

        $_SESSION[self::page]['sql'] = $page['fullSql'];
        //获取自定义字段参数
        $installSearch = $this->installSearch();
        $body          = [];
        //表格控件区
        $liButton = array(
            $this->checkAll("listForm", "listId")
        );
        //获取记录
        $url = root . "control/adIndex.html?cla=" . self::page;
        $editPower = $this->power(self::page, "edit");
        foreach ($page['array'] as $array) {
            //列表控件
            $dominate = array(
                "box" => array("name" => "listId", "value" => $array['id']),
                'edit' => $editPower?array("title" => lang('material.homeSearch.edit'), "click" => "newIframe('" . lang('material.homeSearch.materialDetail') . "','" . $url . "&fun=edit&typeId={$array['typeId']}&id=" . $array['id'] . "')"):[],
                "detail" => array("title" => lang('material.homeSearch.materialDetail'), "click" => "newIframe('" . lang('material.homeSearch.materialDetail') . "','" . $url . "&fun=detail&id=" . $array['id'] . "')"),
            );
            $liButton[] = $this->dominate($dominate);
            //本行初始化
            $row = [];
            foreach ($installSearch['key'] as $key) {
                switch ($key) {
                    case 'bomNum':
                    case 'quarantineNum':
                    case 'routingNum':
                        $row[] = ($array[$key] > 0 ? '是' : '否');
                        break;
                    default:
                        $row[] = isset($array[$key]) && $array[$key] ? $array[$key] : '';
                }
            }
            $body[] = $row;
        }
        //控件
        $button = "";
        //生成页面
        $li = $this->li(array(
            "body" => $body,
            "install" => $installSearch,
            "button" => array("html" => $liButton),
            "orderBySign" => $orderBy,
            "page" => $page['para'],
        ));
        //返回
        $json['html'] = $page['hint'] . $button . "<form name='listForm'>" . $li . "</form>" . $page['button'] . clear;
        $json['html'] .= <<<efo
<script>
var typeId = '{$typeId}'
//优先定位到选择分类的区域
if (typeId !== ''){
    document.getElementsByClassName('active')[0].scrollIntoView({behavior: "smooth", block: "nearest", inline: "center"}); // 滚动到选择的分类
}
</script>
efo;

        return json_encode($json, 320);
    }

    /**
     * 保存分类搜索session
     */
    public function typeSession()
    {
        $_SESSION[$this->post('page')]['keyword'] = $this->post('keyword');
    }
    /**
     * 导出
     */
    public function exportData()
    {
        $templateId = $this->get('templateId');
        $checkedId = $this->get('checkedId')?explode(',',$this->get('checkedId')):[];
        if (!$this->power(self::page, 'export')) {
            $_SESSION['warn'] = '你还没有导出的权限';
        }  else {
            $data = [];
            /***********标题**********/
            $title =[];
            $tempFieldAll = importTemplateClass::templateField(self::page, 'exportFieldInit', id:$templateId);
            foreach ($tempFieldAll as $array) {
                if ($array['display']){
                    $title[] = $array['aliasName'];
                }
            }
            //判断是否选中导出
            if (!self::is_null_array($checkedId)){
                $result = find(array(
                    "table" => self::table,
                    "field" => "*,
            (select ifnull(count(id),0) from bom where coid = '" . self::$coid . "' and state = '启用' and materialId = material.id ) as bomNum,
            (select ifnull(count(id),0) from quarantine where state = '启用' and materialId = material.id ) as quarantineNum,
            (select ifnull(count(id),0) from routing where state = '启用' and materialId = material.id ) as routingNum",
                    "where" => "id in ('".implode("','", $checkedId)."') order by time desc",
                ))['array'];
            }else{
                $sql   = $_SESSION[self::page]['sql'];
                $result   = sqlFind($sql);
            }
            //导出数据生成
            foreach ($result as $array){
                $column = [];
                $type = self::getTypePath($array['typeId']);
                $warehouse = query('warehouse', "id = '$array[warehouse]'");
                $position = query('warehouse_position', "id = '$array[positionId]'");
                foreach ($tempFieldAll as $templateField){
                    if ($templateField['display']){
                        $column[] = match ($templateField['columnName']){
                            '物料名称'=>html_entity_decode($array['name']),
                            '分类'=>$type,
                            '物料编码'=>html_entity_decode($array['code']),
                            '规格型号'=>$array['model'],
                            '主单位'=>$array['unit'],
                            '辅单位1'=>$array['unit_one'],
                            '辅单位一换算'=>self::lostZero($array['unit_one_num'], 'numPrecision'),
                            '辅单位2'=>$array['unit_two'],
                            '辅单位二换算'=> self::lostZero($array['unit_two_num'], 'numPrecision'),
                            '条码'=>$array['barcode'],
                            '备注'=>$array['text'],
                            'OQC(出货检验)'=>$array['OQC'] ? '是' : '否',
                            '销售基准单价元'=>self::lostZero($array['salePrice'], 'pricePrecision'),
                            '销售下浮下限%'=> ($array['downFloat'] * 100),
                            '销售上浮上限%'=>($array['upFloat'] * 100),
                            '默认销售税率%'=> $array['saleRate'] * 100,
                            '来源'=>$array['source'],
                            '供应控制'=>$array['supplyControl'],
                            'IQC(来料检验)'=>$array['IQC'] ? '是' : '否',
                            '采购入库容差(±)%'=> ($array['buyTolerance'] * 100),
                            '采购周期(h)'=>$array['procurement'],
                            '采购单价元'=> self::lostZero($array['buyPrice'], 'pricePrecision'),
                            '采购下浮下限%'=>$array['downBuy'] * 100,
                            '采购上浮上限%'=>$array['upBuy'] * 100,
                            '默认采购税率%'=>$array['buyRate'] * 100,
                            '管理批号'=>$array['isBatch'] ? '是' : '否',
                            '尺寸'=>$array['length'] . '*' . $array['width'] . '*' . $array['height'],
                            '保质期限'=>$array['shelf'] == -1 ? '不限' : $array['shelf'],
                            '重量'=>$array['weight'],
                            '库存上限'=>$array['upStock'] == -1 ? '不限' : self::lostZero($array['upStock'], 'numPrecision'),
                            '库存下限'=>$array['downStock'] == -1 ? '不限' : self::lostZero($array['downStock'], 'numPrecision'),
                            '默认仓库'=>$warehouse['name'],
                            '默认仓位'=>$position['name'],
                            'FQC(制终检验)'=>$array['IPQC'] ? '是' : '否',
                            '生产入库/转序容差(±)%'=> ($array['machiningTolerance'] * 100),
                            '生产周期'=>$array['production'],
                            'OIQC(委外检验)'=> $array['OIQC'] ? '是' : '否',
                            '委外入库容差(±)%'=> $array['outTolerance'] * 100,
                            '委外周期'=>$array['outPeriod'],
                            '存货类型'=>$array['subject'],
                            '成本计价方式'=>$array['costType'],
                            '成本单价'=> self::lostZero($array['costPrice']),
                            '状态'=>$array['state'],
                            '创建人'=> self::findStaff($array['stid']),
                            '创建时间'=>$array['time'],
                            default=>'',
                        };
                    }
                }
                $data[] = $column;
            }
            $text = str_replace(['{{staffName}}'], [$this->control['name']], lang('material.exportData.log'));
            $this->logText(["type" => self::page, "text" => $text]);
            $this->excelOut($title, $data, lang('material.exportData.material') . ".xlsx");
            exit(0);
        }
        header("Location:" . getenv("HTTP_REFERER"));
    }

    /**
     * 下载模板
     */
    public function downloadModel()
    {
        $templateId = $this->get('templateId');
        if (!$this->power(self::page, 'edit')) {
            $_SESSION['warn'] = '你还没有编辑的权限';
        } else {
            $exampleData[] = ['办公用品>打印机', 'RT20121','打印机', 'TT01', '台', '', '', '', '', '样例数据，导入时请删除此条数据', '是', 5, 0.1, 0.2, 0.01, '自制', '允许生产,允许采购,允许库存', '是', 0, 10, 1, 0.1, 0.1, 0.01, '是', '10*5*3', 180, 10, 300, 10, '默认仓库', '默认仓位', '是', 0, 30, '否', 0, '', '产成品', '先进先出', 2];
            $excel    = $this->excelHead();
            $fileName = self::title.'导入模板-'.importTemplateClass::getName($templateId).'.xlsx';
            $filePath = $excel->fileName($fileName, 'sheet1');
            $format = new \Vtiful\Kernel\Format($filePath->getHandle());
            $templateField = importTemplateClass::templateField(self::page, 'importFieldInit', id:$templateId);
            $index         = 0;
            foreach ($templateField as $k => $array) {
                if ($array['display']){
                    $backgroundStyle=null;
                    if (importTemplateClass::getIsMustValue($this->importFieldInit(), $array['columnName'])){
                        //必填项判断
                        $backgroundStyle  = $format->background(
                            0xFFC04B
                        )->toResource();
                    }
                    $filePath->insertText(0, $index, $array['aliasName'],'',$backgroundStyle);
                    foreach ($exampleData as $y=>$example){
                        $exampleVal = match ($array['columnName']){
                            '分类'=>$example[0],
                            '物料编码'=>$example[1],
                            '物料名称'=>$example[2],
                            '规格型号'=>$example[3],
                            '主单位'=>$example[4],
                            '辅单位1'=>$example[5],
                            '辅单位一换算'=>$example[6],
                            '辅单位2'=>$example[7],
                            '辅单位二换算'=>$example[8],
                            '备注'=>$example[9],
                            'OQC出货检验'=>$example[10],
                            '销售基准单价'=>$example[11],
                            '销售下浮下限'=>$example[12],
                            '销售上浮上限'=>$example[13],
                            '默认销售税率'=>$example[14],
                            '来源'=>$example[15],
                            '供应控制'=>$example[16],
                            'IQC来料检验'=>$example[17],
                            '采购入库容差'=>$example[18],
                            '采购周期'=>$example[19],
                            '采购单价'=>$example[20],
                            '采购下浮下限'=>$example[21],
                            '采购上浮上限'=>$example[22],
                            '默认采购税率'=>$example[23],
                            '管理批号'=>$example[24],
                            '尺寸'=>$example[25],
                            '保质期限'=>$example[26],
                            '重量'=>$example[27],
                            '库存上限'=>$example[28],
                            '库存下限'=>$example[29],
                            '默认仓库'=>$example[30],
                            '默认仓位'=>$example[31],
                            'FQC制终检验'=>$example[32],
                            '生产入库/转序容差'=>$example[33],
                            '生产周期'=>$example[34],
                            'OIQC委外检验'=>$example[35],
                            '委外入库容差'=>$example[36],
                            '委外周期'=>$example[37],
                            '存货类型'=>$example[38],
                            '成本计价方式'=>$example[39],
                            '成本单价'=>$example[40],
                            default=>'',
                        };
                        $filePath->insertText($y+1, $index, $exampleVal);
                    }
                    $index++;
                }
            }
            $text = $this->control['name'] . str_replace(['{{staffName}}'], [$this->control['name']], lang('material.downloadModel.log'));
            $this->logText(["type" => self::page, "text" => $text]);
            $this->excelOutPut($filePath,$fileName);
        }
        exit(0);
    }

    public static function createType($str){
        //多级分类分割
        if (str_contains($str,"-&gt;")){
            $typeArr = explode("-&gt;", $str);
        }else{
            $typeArr = explode("&gt;", $str);
        }
        if (is_array($typeArr)) {
            $pid = '0';
            foreach ($typeArr as $name) {
                $type = query('material_type', "name = '$name' and pid = '$pid' and coid = '" . self::$coid . "'");
                if (empty($type['id'])) {
                    $typeField = [
                        'id' => self::getId(),
                        'coid' => self::$coid,
                        'pid' => $pid ?: '0',
                        "name" => $name,      //部门名称
                        "list" => 0,      //排序号
                    ];
                    insert(array('table' => 'material_type', "field" => $typeField));
                    $pid = $typeField['id'];
                    $type['id'] = $typeField['id'];
                } else {
                    $pid = $type['id'];
                }
            }
        }
        return $type['id']??'';
    }

    /*数据导入分析*/
    public function importData()
    {
        $templateId = $this->post('templateId');
        if (!$this->power(self::page, 'edit')) {
            $json['warn'] = lang('material.importData.power');
        } else {
             $fomatArray = [];//导入数据格式同一为TYPE_STRING
            foreach ($this->importFieldInit() as $value){
                $fomatArray[] = \Vtiful\Kernel\Excel::TYPE_STRING;
            }
            $data = $this->importHead(format: $fomatArray);
            $x = 0;
            $text = '';
            $headArray = [];
            $row_list=0;
            foreach ($data as $i => $row) {
                $row_list++;
                if ($i==0){
                    $templateField = importTemplateClass::templateField(self::page, 'importFieldInit', id:$templateId);
                    $headArray = importTemplateClass::combinHead($templateField,$row);
                }
                if ($i > 0) {
                    $rowData = formSubArray($row);

                    //只接收模板中选中的字段的值
                    $cell = [];
                    foreach ($headArray as $index=>$headName){
                        $cell[$headName] = $rowData[$index]??'';
                    }
                    //初始化未被模板需要的字段的值
                    foreach ($this->importFieldInit() as $value){
                        $cell[$value['columnName']] = $cell[$value['columnName']]??'';
                    }

                    //多级分类分割
                    $type['id'] = self::createType($cell['分类']);
                    $size = explode('*', $cell['尺寸']);
                    $warehouse = query('warehouse', "name = '$cell[默认仓库]' and coid = '" . self::$coid . "' and state = '启用'");
                    $position = query('warehouse_position', "name = '$cell[默认仓位]' and orderId = '$warehouse[id]' and coid = '" . self::$coid . "' and state = '启用'");
                    $supplyControlOption = explode(',', $cell['供应控制']);
                    $field = [
                        'typeId' => $type['id'] ?? '',
                        'typePath' => self::getTypePath($type['id'],'id','/'),
                        'typeName' => self::getTypePath($type['id']),
                        "code" => $cell['物料编码'],
                        "name" => $cell['物料名称'],
                        "model" => $cell['规格型号'],
                        "unit" => $cell['主单位'],
                        "unit_one" => $cell['辅单位1'],
                        "unit_one_num" => self::formattingFigure($cell['辅单位一换算'],'numPrecision'),
                        "unit_two" => $cell['辅单位2'],
                        "unit_two_num" => self::formattingFigure($cell['辅单位二换算'],'numPrecision'),
                        "barcode" => self::creatBarCode(),
                        "text" => $cell['备注'],
                        "OQC" => $cell['OQC出货检验'] == '是' ? 1 : 0,
                        "salePrice" => (float)$cell['销售基准单价'],
                        "downFloat" => (float)$cell['销售下浮下限'] / 100,
                        "upFloat" => (float)$cell['销售上浮上限'] / 100,
                        "saleRate" => (float)$cell['默认销售税率'] / 100,
                        "source" => $cell['来源'],
                        "supplyControl" => $cell['供应控制'],
                        "IQC" => $cell['IQC来料检验'] == '是' ? 1 : 0,
                        'buyTolerance' => (float)$cell['采购入库容差'] / 100,
                        "procurement" => $cell['采购周期'],
                        "buyPrice" => self::formattingFigure($cell['采购单价'], 'pricePrecision'),
                        "downBuy" => (float)$cell['采购下浮下限'] / 100,
                        "upBuy" => (float)$cell['采购上浮上限'] / 100,
                        "buyRate" => (float)$cell['默认采购税率'] / 100,
                        "isBatch" => $cell['管理批号'] == '是' ? 1 : 0,
                        "length" => $size[0] ?? '',
                        "width" => $size[1] ?? '',
                        "height" => $size[2] ?? '',
                        "shelf" => $cell['保质期限'] > 0 ? $cell['保质期限'] : -1,
                        "weight" => $cell['重量'],
                        "upStock" => $cell['库存上限'] > 0 ? self::formattingFigure($cell['库存上限'], 'numPrecision') : -1,
                        "downStock" => $cell['库存下限'] > 0 ? self::formattingFigure($cell['库存下限'], 'numPrecision') : -1,
                        "warehouse" => $warehouse['id'],
                        "positionId" => $position['id'],
                        "IPQC" => $cell['FQC制终检验'] == '是' ? 1 : 0,
                        "machiningTolerance" => (float)$cell['生产入库/转序容差'] / 100,
                        "production" => $cell['生产周期'],
                        "OIQC" => $cell['OIQC委外检验'] == '是' ? 1 : 0,
                        "outTolerance" => (float)$cell['委外入库容差'] / 100,
                        "outPeriod" => $cell['委外周期'],
                        "subject" => $cell['存货类型'] ?: '产成品',
                        "costType" => $cell['成本计价方式'] ?: '移动加权平均',
                        "costPrice" => self::formattingFigure($cell['成本单价'], 'pricePrecision'),
                    ];
                    $annotation = [
                        'typeId' => lang('material.importData.typeId'),
                        'code' => lang('material.importData.code'),
                        'name' => lang('material.importData.name'),
                        'unit' => lang('material.importData.unit'),
                        'OQC' => lang('material.importData.OQC'),
                        'source' => lang('material.importData.source'),
                        'supplyControl' => lang('material.importData.supplyControl'),
                        'IQC' => lang('material.importData.IQC'),
                        'isBatch' => lang('material.importData.isBatch'),
                        'shelf' => lang('material.importData.shelf'),
                        'IPQC' => lang('material.importData.IPQC'),
                        'subject' => lang('material.importData.subject'),
                        'costType' => lang('material.importData.costType'),
                    ];
                    $rules = [
                        'typeId' => 'required',
                        'code' => 'required',
                        'name' => 'required',
                        'unit' => 'required',
                        'OQC' => 'required',
                        'supplyControl' => 'required',
                        'source' => 'required',
                        'IQC' => 'required',
                        'isBatch' => 'required',
                        'shelf' => 'required',
                        'IPQC' => 'required',
                        'subject' => 'required',
                        'costType' => 'required',
                    ];
                    $resOption = $this->supplyControlOption($field['source']);
                    // 校验是否符合规则
                    $vt = new \verify();
                    $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();

                    $query = query(self::table, " code = '$field[code]' and coid = '" . self::$coid . "' ");
                    //导入重复处理
                    $optionSetting = optionSettingClass::getSetting('公共');  //选项设置
                    $companyRepeatItemCtrl = $optionSetting['materialRepeatDeal'];
                    if ($result === false) {
                        $text .= str_replace(['{{i}}', '{{error}}'], [$row_list, $vt->getErrs()[0]], lang('material.importData.error')) . "<br>";  // 多个规则提示最前面一条
                        //开启选项设置禁止重复，或者未开启选项设置
                    } elseif (($companyRepeatItemCtrl['option'] == 1 && $companyRepeatItemCtrl['method'] == 'ban' && !empty($query['id'])) || (!$companyRepeatItemCtrl['option'] && !empty($query['id']))) {
                        $text .= str_replace(['{{i}}'], [$row_list], lang('material.importData.repeat')) . "<br>";
                    } elseif (!empty($cell[31]) && empty($position['id'])) {
                        $text .= str_replace(['{{i}}'], [$row_list], lang('material.importData.notFind')) . "<br>";
                    } elseif (($field['unit_one'] || $field['unit_two']) && ($field['unit_one'] == $field['unit_two'] || $field['unit'] == $field['unit_two'] || $field['unit'] == $field['unit_one'])) {
                        $text .= str_replace(['{{i}}'], [$row_list], lang('material.importData.noCommon')) . "<br>";
                    } elseif (!in_array($field['source'], $this->sourceOption)) {
                        $text .= str_replace(['{{i}}'], [$row_list], lang('material.importData.notInSource')) . "<br>";
                    } else {

                        $flag = true;
                        foreach ($supplyControlOption as $val) {
                            if (!in_array($val, array_keys($resOption))) {
                                $text .= str_replace(['{{i}}'], [$row_list], lang('material.importData.notInSupply')) . "<br>";
                                $flag = false;
                                break;
                            }
                            foreach ($resOption as $key => $option) {
                                if ($key == $val && $option['attr'] == 'disabled') {
                                    $text .= str_replace(['{{i}}'], [$row_list], lang('material.importData.sourceSupply')) . "<br>";
                                    $flag = false;
                                    break;
                                }
                            }
                        }
                        if ($flag) {
                            if ($companyRepeatItemCtrl['option'] == 1 && $companyRepeatItemCtrl['method'] == 'cover' && !empty($query['id'])) {
                                $warn = update(["table" => self::table, "field" => $field, "where" => "id = '" . $query['id'] . "'"]);
                                $field['id'] = $query['id'];
                            } else {
                                $field = array_merge($field, ['id' => self::getId(), 'coid' => self::$coid, 'stid' => self::$stid, 'state' => '启用']);
                                $warn = insert(["table" => self::table, "field" => $field]);
                            }
                            if (in_array($warn, ["新增成功", "更新成功"])) {
                                $x++;
                                $text .= "第【{$row_list}】行：导入成功<br>";
                            } else {
                                $text .= "第【{$row_list}】行：导入失败：编辑失败<br>";
                            }
                        }
                    }

                }
            }
            self::getSidebarData(reset: true); //重置左侧分类导航栏
            $total = count($data)-1;
            $json['data'] = [
                'text'=>$text,
                'title'=>"您导入了{$total}条数据，成功{$x}条，失败".($total-$x)."条",
            ];
            $text = str_replace(['{{staffName}}', '{{fileName}}'], [$this->control['name'], $_FILES['file']['name']], lang('material.importData.log')) . '：' . $text;
            $warn = $this->logText(["type" => self::page, "text" => $text]);
            $json['warn'] = 2;
        }
        return json_encode($json,320);
    }

    /**
     * 设置科目
     * @return false|string
     */
    public function settingSubject()
    {
        //生成表单
        $html = $this->layerEdit(array("table" => array(
            array(
                '存货科目' => componentClass::subjectSelect(isShowParent: false),
            ),
            array(
                '销售成本' => componentClass::subjectComponent(['name' => 'costSubjectId', 'inputName' => 'costSubjectName', 'isShowParent' => false])
            ),
            array(
                '销售收入' => componentClass::subjectComponent(['name' => 'incomeSubjectId', 'inputName' => 'incomeSubjectName', 'isShowParent' => false])
            ),
            array(must.'类型'=>radio(['name'=>'type','value'=>['choosed'=>'选中的物料','all'=>'所有物料'],'checked'=>'choosed']))
        )));
        //返回
        return $this->layer(array("title" => '设置科目', "height" => 400, "width" => 800, "html" => $html, 'formTwo' => 'listForm'));
    }
    /**
     * 启用/停用
     */
    public function settingSubjectEdit(): bool|string
    {
        $idArr = $this->post('listId');
        $field = [
            'subjectId'=>$this->post('subjectId'),
            'costSubjectId'=>$this->post('costSubjectId'),
            'incomeSubjectId'=>$this->post('incomeSubjectId'),
        ];
        $type = $this->post('type');
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = lang('material.stateSwitchEdit.power');
        } elseif ($type !='all' && (empty($idArr) || !is_array($idArr))) {
            $json['warn'] = lang('material.stateSwitchEdit.choice');
        } elseif (empty($field['subjectId']) && empty($field['costSubjectId']) && empty($field['incomeSubjectId'])) {
            $json['warn'] ='请至少选择一项科目';
        } else {
            if ($type !='all'){
                $json['warn'] = static::update(array('table' => self::table, 'field' => $field, 'where' => " id in ('" . implode("','", $idArr) . "')"),false);
            }else{
                $json['warn'] = static::update(array('table' => self::table, 'field' => $field, 'where' => " 1=1"),false);
            }
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                //添加日志
                $text = $this->control['name'].'给物料档案批量设置了科目';
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn'] = 2;
            }
        }
        //返回
        return json_encode($json, 320);
    }
    /**
     * 启用/停用
     */
    public function stateSwitch(): bool|string
    {
        $type = $this->post('type');
        //生成表单
        $html = $this->layerEdit(array("table" => array(
            array(
                lang('material.stateSwitch.tips') => lang('material.stateSwitch.modify') . $type,
            ),
        ), 'hidden' => hidden(array('name' => 'type', 'value' => $type))));
        //返回
        return $this->layer(array("title" => lang('material.stateSwitch.switching'), "height" => 165, "html" => $html, 'formTwo' => 'listForm'));
    }

    /**
     * 启用/停用
     */
    public function stateSwitchEdit(): bool|string
    {
        $idArr = $this->post('id') ? [$this->post('id')] : $this->post('listId');
        $state = $this->post('type');
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = lang('material.stateSwitchEdit.power');
        } elseif (empty($idArr) || !is_array($idArr)) {
            $json['warn'] = lang('material.stateSwitchEdit.choice');
        } elseif (!in_array($state, ['启用', '停用'])) {
            $json['warn'] = lang('material.stateSwitchEdit.typeError');
        } else {
            $field = [
                'state' => $state,
            ];
            //存货库存有余额时可以停用
            $warn = '';
            if (!optionSettingClass::getSettingItem('公共', 'materialStop') && $state == '停用') {
                foreach ($idArr as $k => $materialId) {
                    $material = query("material", " id = '$materialId' ", "name");
                    $balance = find([
                            'table' => "inventory_record",
                            'field' => "IFNULL(sum(num), 0) as total",
                            'single' => " 1=1 and coid = '" . self::$coid . "' and materialId = '$materialId' ",
                        ])['total'] ?? 0;
                    if ($balance > 0) {
                        $warn .= str_replace(['{{name}}'], [$material['name']], lang('material.stateSwitchEdit.warn'));
                        unset($idArr[$k]);
                    }
                }
            }
            $json['warn'] = update(array('table' => self::table, 'field' => $field, 'where' => " id in ('" . implode("','", $idArr) . "')"));
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                //添加日志
                $materialArr = find(array('table' => self::table, 'field' => "concat('编码：',code,'，名称：',name) as name", 'where' => " coid = '" . self::$coid . "' and id in ('".implode("','", $idArr)."') "));
                $name = $materialArr['array'] ? implode('，',(array)array_column($materialArr['array'],'name')) : '无';
                $type = mb_substr($json['warn'], 0, 2, 'utf-8');
                $text = str_replace(['{{staffName}}', '{{type}}', '{{state}}', '{{ids}}'], [$this->control['name'], $type, $state, $name], lang('material.stateSwitchEdit.log'));
                $this->logText(["type" => self::page, "text" => $text . $warn]);
                //返回
                $_SESSION['warn'] = $state . count($idArr) .'个物料';
                $json['warn'] = 2;
            }
        }
        //返回
        return json_encode($json, 320);
    }

    /**
     * Desc : 获取分类路径
     * User : you name
     * Date : 2023-12-27 13:51
     * @param $id
     * @param string $field
     * @param string $split
     * @return mixed
     */
    public static function getTypePath($id, $field='name', $split='>'): mixed
    {
        $type = query(self::table . '_type', "id = '$id'");
        if (!empty($type['pid'])) {
            $result = self::getTypePath($type['pid'], $field, $split);
            $name = $result . $split . $type[$field];
        } else {
            $name = $type[$field] ?? null;
        }
        return $name;
    }

    /*基本资料-弹出层*/
    public function edit(): string
    {
        $id = $this->get('id') ?? self::getId();
        $info = query(self::table, " id = '" . $id . "' ");
        $button[] = [
            "name" => lang('material.edit.save'),
            "type" => "点击事件",
            "fun" => "subForm('" . self::page . "EditForm','" . root . "control/adIndex.html?cla=" . self::page . "&fun=editEdit')",
            'style' => 'li-btn-blue-bg',
        ];
        $button[] = [
            "name" => lang('material.edit.saveNew'),
            "type" => "点击事件",
            "fun" => "subForm('" . self::page . "EditForm','" . root . "control/adIndex.html?cla=" . self::page . "&source=home&fun=editEdit')",
        ];
        $tipUnit = self::tipComponent(lang('material.edit.unitTip'));

        $materialTypeBtn = $info['id'] ? "<span class='del-row-button' onclick=\"layer('routing','materialType',{})\" style='margin-left: 10px'>" . lang('material.edit.cut') . "</span>" : '';
        $position = query('warehouse_position', "id = '$info[positionId]'");
        $warehouse = query('warehouse', "id = '$position[orderId]'");

        $typeId = $info['typeId'] ?: $this->get('typeId');
        $type_name = $info['typeName']?:self::getTypePath($typeId);
        //生成编码,此处为特殊处理
        if (empty($info['code'])) {
            $material_type = explode('->', $type_name);
            $material_field = [
                'oneType' => isset($material_type[0]) ? PYClass::encode($material_type[0], strtoupper: true) : '',
                'twoType' => isset($material_type[1]) ? PYClass::encode($material_type[1], strtoupper: true) : '',
                'threeType' => isset($material_type[2]) ? PYClass::encode($material_type[2], strtoupper: true) : '',
            ];
            $info['code'] = codeTemplateClass::generateCode(self::page, [
                'prefix' => 'WL' . date('Ymd'),
                'table' => self::table,
                'field' => 'code',
                'where' => " and coid = '" . self::$coid . "' ",
            ], $material_field);
        }

        $readonly = "";
        //设置编码不能修改，并且已使用
        if (!optionSettingClass::getSettingItem('公共', 'materialCode') && (static::total(array('table' => 'sale_order_detail', 'where' => "materialId = '$id'")) > 0 || static::total(array('table' => 'purchase_order_detail', 'where' => "materialId = '$id'")) > 0 || static::total(array('table' => 'inventory_record', 'where' => "materialId = '$id'")) > 0)) {
            $readonly = "readonly";
        }

        //管理批号及保质期控制
        $optionSetting = optionSettingClass::getSetting('公共');  //选项设置
        $batchCtrl = $optionSetting['batchCtrl'];
        $bacth = [];
        if ($batchCtrl['option'] && $batchCtrl['period']) {
            $bacth = [
                must . lang('material.edit.isBatch') . "：" => radio(array('name' => 'isBatch', 'value' => ['1' => '是', '0' => '否'], 'checked' => $info['id'] ? $info['isBatch'] : '1')),
                lang('material.edit.size') . "：" => text(array('name' => 'length', 'type' => 'number', 'title' => lang('material.edit.length'), 'value' => $info['length'])) . "* " .
                    text(array('name' => 'width', 'type' => 'number', 'title' => lang('material.edit.width'), 'value' => $info['width'])) . '* ' .
                    text(array('name' => 'height', 'type' => 'number', 'title' => lang('material.edit.height'), 'value' => $info['height'])),
                must . lang('material.edit.shelf') . '：' => radio(array('name' => 'shelf', 'value' => ['-1' => '不限', '1' => "&nbsp;" . text(['name' => 'shelfDay', 'type' => 'number', 'unit' => '天', 'value' => $info['shelf'] != -1 ? $info['shelf'] : ''])], 'checked' => ($info['shelf'] != -1 && !empty($info['shelf'])) ? '1' : '-1')),
            ];
        } elseif (!$batchCtrl['option'] && !$batchCtrl['period']) {
            $bacth = [
                lang('material.edit.size') . "：" => text(array('name' => 'length', 'type' => 'number', 'title' => lang('material.edit.length'), 'value' => $info['length'])) . "* " .
                    text(array('name' => 'width', 'type' => 'number', 'title' => lang('material.edit.width'), 'value' => $info['width'])) . '* ' .
                    text(array('name' => 'height', 'type' => 'number', 'title' => lang('material.edit.height'), 'value' => $info['height'])) .
                    hidden(array("name" => "isBatch", "value" => '0')),
            ];
        } elseif ($batchCtrl['option'] && !$batchCtrl['period']) {
            $bacth = [
                must . lang('material.edit.isBatch') . "：" => radio(array('name' => 'isBatch', 'value' => ['1' => '是', '0' => '否'], 'checked' => $info['id'] ? $info['isBatch'] : '1')),
                lang('material.edit.size') . "：" => text(array('name' => 'length', 'type' => 'number', 'title' => lang('material.edit.length'), 'value' => $info['length'])) . "* " .
                    text(array('name' => 'width', 'type' => 'number', 'title' => lang('material.edit.width'), 'value' => $info['width'])) . '* ' .
                    text(array('name' => 'height', 'type' => 'number', 'title' => lang('material.edit.height'), 'value' => $info['height'])),
            ];
        } elseif (!$batchCtrl['option'] && $batchCtrl['period']) {
            $bacth = [
                lang('material.edit.size') . "：" => text(array('name' => 'length', 'type' => 'number', 'title' => lang('material.edit.length'), 'value' => $info['length'])) . "* " .
                    text(array('name' => 'width', 'type' => 'number', 'title' => lang('material.edit.width'), 'value' => $info['width'])) . '* ' .
                    text(array('name' => 'height', 'type' => 'number', 'title' => lang('material.edit.height'), 'value' => $info['height'])) .
                    hidden(array("name" => "isBatch", "value" => '0')),
                must . lang('material.edit.shelf') . '：' => radio(array('name' => 'shelf', 'value' => ['-1' => '不限', '1' => "&nbsp;" . text(['name' => 'shelfDay', 'type' => 'number', 'unit' => '天', 'value' => $info['shelf'] != -1 ? $info['shelf'] : ''])], 'checked' => ($info['shelf'] != -1 && !empty($info['shelf'])) ? '1' : '-1')),
            ];
        }
        //销售单价
        $salePriceArr = ($this->power('material','editPrice')?
            [
                lang('material.edit.salePrice') . "：" => text(array('name' => 'salePrice', 'other' => self::digitalFiltering('pricePrecision'), 'unit' =>  static::$unit , 'value' => self::lostZero($info['salePrice'], 'pricePrecision'))),
                lang('material.edit.upBuy') . "：" => text(array('name' => 'downFloat', 'type' => 'number', 'unit' => '%', 'value' => (float)$info['downFloat'] * 100)),
                lang('material.edit.downFloat') . "：" => text(array('name' => 'upFloat', 'type' => 'number', 'unit' => '%', 'value' => (float)$info['upFloat'] * 100)),
                lang('material.edit.saleRate') . "：" => select(array('name' => 'saleRate', 'option' => explode('，', para('taxRate')), 'title' => lang('material.edit.choice'), 'value' => (float)$info['saleRate'] * 100)),
            ]:
            [
                lang('material.edit.upBuy') . "：" => text(array('name' => 'downFloat', 'type' => 'number', 'unit' => '%', 'value' => (float)$info['downFloat'] * 100)),
                lang('material.edit.downFloat') . "：" => text(array('name' => 'upFloat', 'type' => 'number', 'unit' => '%', 'value' => (float)$info['upFloat'] * 100)),
                lang('material.edit.saleRate') . "：" => select(array('name' => 'saleRate', 'option' => explode('，', para('taxRate')), 'title' => lang('material.edit.choice'), 'value' => (float)$info['saleRate'] * 100)),
            ]
        );
        //采购单价
        $buyPriceArr = ($this->power('material','editPrice')?
            [
                lang('material.edit.buyPrice') . "：" => text(array('name' => 'buyPrice', 'other' => self::digitalFiltering('pricePrecision'), 'unit' =>  static::$unit , 'value' => self::lostZero($info['buyPrice'], 'pricePrecision'))),
                lang('material.edit.downBuy') . "：" => text(array('name' => 'downBuy', 'type' => 'number', 'unit' => '%', 'value' => (float)$info['downBuy'] * 100)),
                lang('material.edit.upBuy') . "：" => text(array('name' => 'upBuy', 'type' => 'number', 'unit' => '%', 'value' => (float)$info['upBuy'] * 100)),
                lang('material.edit.buyRate') . "：" => select(array('name' => 'buyRate', 'option' => explode('，', para('taxRate')), 'title' => lang('material.edit.choice'), 'value' => (float)$info['buyRate'] * 100)),
            ]:
            [
                lang('material.edit.downBuy') . "：" => text(array('name' => 'downBuy', 'type' => 'number', 'unit' => '%', 'value' => (float)$info['downBuy'] * 100)),
                lang('material.edit.upBuy') . "：" => text(array('name' => 'upBuy', 'type' => 'number', 'unit' => '%', 'value' => (float)$info['upBuy'] * 100)),
                lang('material.edit.buyRate') . "：" => select(array('name' => 'buyRate', 'option' => explode('，', para('taxRate')), 'title' => lang('material.edit.choice'), 'value' => (float)$info['buyRate'] * 100)),
            ]
        );
        //成本单价
        $costPriceArr = ($this->power('material','editPrice')?
            [
                lang('material.edit.costPrice') . '：' => text(array('name' => 'costPrice', 'other' => self::digitalFiltering('pricePrecision'), 'value' => self::lostZero($info['costPrice'], 'pricePrecision'))),
                lang('material.edit.location') . '：' => "<span style='position: relative'>" . text(array('name' => 'location', 'value' => $warehouse['name'] . ' ' . $position['name'], 'class' => 'text', 'id' => 'locationCode', 'other' => 'readOnly')) . hidden(array('name' => 'positionId', 'value' => $info['positionId'])) . "<img onclick=\"layer('moveStock','choiceLocation')\" style='position:absolute;right:10px;top:1px;cursor: pointer;' src='" . root . "img/control/find.svg?v=2'/></span>"
            ]:
            [
                lang('material.edit.location') . '：' => "<span style='position: relative'>" . text(array('name' => 'location', 'value' => $warehouse['name'] . ' ' . $position['name'], 'class' => 'text', 'id' => 'locationCode', 'other' => 'readOnly')) . hidden(array('name' => 'positionId', 'value' => $info['positionId'])) . "<img onclick=\"layer('moveStock','choiceLocation')\" style='position:absolute;right:10px;top:1px;cursor: pointer;' src='" . root . "img/control/find.svg?v=2'/></span>"
            ]
        );

        //属性
        $material_attr_scheme = query("material_attr_scheme", " id = '$info[scheme]' ", "id,name"); //属性方案
        $tip                  = self::tipComponent(lang('material.edit.unitTip'));
        $tr[]                 = ['{l.material.edit.attr}', '{l.material.edit.unitOne}' . $tip, '{l.material.edit.unitTwo}' . $tip, '{l.material.edit.barcode}', '{l.material.edit.operate}'];
        if ($info['id']) {
            $result = find(array('table' => self::table . '_sku', 'where' => "materialId = '$info[id]' order by list asc"));
            foreach ($result['array'] as $array) {
                $resultMx  = find(array('table' => self::table . '_sku_detail', 'where' => "skuId = '$array[id]' and materialId = '$info[id]' order by list"));
                $attr_name = $hidden = '';
                foreach ($resultMx['array'] as $index => $val) {
                    $attr_mx = query(self::table . '_attr_detail', " id = '$val[attrMxId]'");
                    if ($index > 0) {
                        $attr_name .= '，';
                    }
                    $attr_name .= $attr_mx['value'];
                    $hidden    .= hidden(array('name' => "combinationMxId[{$array['id']}][]", 'value' => $val['attrMxId']));
                }

                $tr[] = [
                    $attr_name . hidden(array('name' => 'combinationId[]', 'value' => $array['id'])) . hidden(array('name' => 'attr_name[]', 'value' => $attr_name)) . $hidden,
                    text(array('name' => 'help_unit_one[]', 'other' => self::digitalFiltering('numPrecision'), 'value' => self::lostZero($array['unitOne'], 'numPrecision'))),
                    text(array('name' => 'help_unit_two[]', 'other' => self::digitalFiltering('numPrecision'), 'value' => self::lostZero($array['unitTwo'], 'numPrecision'))),
                    text(array('name' => 'barcode[]', 'value' => $array['barcode'])),
                    "<span onclick='decline(this)' class='del-row-button'>" . lang('material.edit.del') . "</span>"
                ];
            }
        } else {
            $material_attr_scheme = query("material_attr_scheme", " coid = '" . self::$coid . "' and name = '默认方案' ", "id,name"); //属性方案
            $tr                   = array_merge($tr, $this->defaultScheme($material_attr_scheme['id']));
        }
        $attrGroup    = $this->tableMany(['tr' => $tr]);
        $scheme       = must . lang('material.edit.scheme') . "：<input id='schemeInput' name='schemeName' type='text' placeholder='" . lang('material.edit.schemePlaceholder') . "' value='{$material_attr_scheme['name']}'>" . hidden(array("name" => "scheme", "value" => $material_attr_scheme['id']));
        $manageScheme = lang('material.edit.manageScheme');
        $attrHtml     = <<<efo
<li>
    <div class="attr-content" style="width: 100%;">
        <div class="choice-scheme">{$scheme}<span class="spanButton" onclick="layer('{$this->get('cla')}','attrScheme',{})">{$manageScheme}</span></div>
        <div class="attr-group" id="attr-group">
            {$attrGroup}
        </div>
</div>

<style>
.choice-scheme{
    margin: 10px 20px;
    position: relative;
}
.attr-content ul li{
   float: left;
   margin: 5px;
}
.attr-content ul{
  display: flex;
  flex-wrap: wrap;
}
.attr-content>ul>li:nth-child(1) {
    text-align: right;
    width: 75px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.attr-content>ul:nth-child(n+2){
   background-color: #F2F2F2;
}
#attr-table tr:hover{
   background:none;
}
#attr-table thead tr:nth-child(1){
  background-color: #F2F2F2;
}
#attr-table .tableManyClick{
  background-color: white;
}
#attr-table ul li{
  float: left;
  margin: 5px;
}
.add-attr-button{
    border: 2px solid #6aacfb;
    color: #6aacfb;
    font-weight: bold;
    font-size: 21px;
    width: 16px;
    height: 16px;
    text-align: center;
    line-height: 13px;
    cursor: pointer;
    border-radius: 2px;
}
#attr-table .tableMany th, .tableMany td{
   vertical-align: middle;
}
.radioDisabled{  
    background-color: rgb(0 0 0/10%)!important;
}

</style>
<script>
function setAllCheck(e){
    $("[name='attr[]']").each(function(i) {
        let val = $(this).val();
       if ($(this).prop("checked")){
           $("input[name='attr_mx["+val+"][]']").prop("checked","checked")
       }else{
           $("input[name='attr_mx["+val+"][]']").prop("checked","")
       }
    });
}
//展示输入框
function showInput(e){
    let id = $(e).parent().parent().parent().parent().find("input[name='attrId[]']").val();
    $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=showInput',{id:id},function (res){
        $(e).parent().before(res.html);
        $(e).css('display','none');
    },'json');
}
//展示添加按钮
function showAddButton(e){
    let val = e.value;
    let id = $(e).parent().parent().parent().parent().find("input[name='attrId[]']").val();
    $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=showAddButton',{id:id,val:val},function (res){
        $(e).parent().after(res.html);
        $(e).parent().remove();
        $(".add-attr-button").css('display','inline-flex');
    },'json');

}
function commitData(){
        //异步提交数据
    let serialize = $("[name='attrForm']").serialize();
    $.post(root+'control/adIndex.html?cla=material&fun=addAttrEdit', serialize, function(data) {
        $('#materialAddAttr').hide();
      if (data.warn == 2) {
         $.post(root+'control/adIndex.html?cla=material&fun=getAttr', {}, function(res) {
             $(".attr-type").empty().append(res.type)
             $("#attr-catalog").empty().append(res.html)
         },'json');
      } else {
        warn(data.warn);
      }
    }, "json");
}
function del_this(e){
    $(e).parent().remove();
}
//添加一行
function addRow(){
    $.post(root+'control/adIndex.html?cla=material&fun=addRow',{},function (res){
        $("#attr-table .tableMany tr:last").after(res.html);
    },'json')
}
//生成组合
function combination(){
     let para = $("form[name='materialEditForm']").serialize();

    $.post(root+'control/adIndex.html?cla=material&fun=combination',para,function (res){
        $("#attr-group").empty().append(res.html);
    },'json')
}
//切换分类
         function chooseMaterialType(e){    
             let id = $(e).data('id');
             let materialId = $("[name='id']").val();
             if (id){
                 $.post(root+'control/adIndex.html?cla=material&fun=changeMaterialType',{id:id,materialId:materialId},function(res) {
                     if (res.warn ==2){
                         location.reload();
                     }else{
                         msg(res.warn,'error')
                     }
                 },'json')
             }
         }
         //切换来源
         function getSupplyControl(e){
             $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=getSupplyControl',{source:e.value},function(res) {
                $('#supplyControl').html(res.html)
             },'json')
         }
                     //选择仓位
        function addTarget(){
            $.post(root+'control/adIndex.html?cla=moveStock&fun=addTargetEdit', $("form[name='locationForm']").serialize(),function(resp) {
                 if (resp.warn === 2){
                    $('#locationCode').val(resp.text)
                    $("[name='positionId']").val(resp.id)
                 }else{
                     msg(resp.warn);
                 }
            },'json');
        }
        //查询属性方案名称
        function serchScheme(e){
             let keyword = $(e).siblings("input").val();
            $.post(root+'control/adIndex.html?cla=material&fun=serchScheme',{keyword:keyword},function (res){
                $("#navigationDiv").html(res.html)
            },'json')
        }
        //保存属性方案
        function schemeEdit(){
             let para = $("form[name='attrSchemeForm']").serialize();
            $.post(root+'control/adIndex.html?cla=material&fun=schemeEdit',para,function (res){
                if(res.warn == 2){
                     msg('保存成功','success')
                     $("[data-id='"+res.id+"']").text(res.name)
                     if(res.html !== ''){
                        $(".scheme-menu").removeClass("scheme-menu-choice")
                        $("#navigationDiv").append(res.html)
                    }
                }else{
                    msg(res.warn,'error')
                }
            },'json')
        }
        //删除属性方案
        function delScheme(){
             let para = $("form[name='attrSchemeForm']").serialize();
            $.post(root+'control/adIndex.html?cla=material&fun=delScheme',para,function (res){
                if(res.warn == 2){
                     $("[data-id='"+res.id+"']").remove()
                     $("[data-id='']").click()
                }else{
                    msg(res.warn,'error')
                }
            },'json')
        }
        function switchingScheme(e){
            var id = $(e).data('id');
            $.post(root+'control/adIndex.html?cla=material&fun=switchingScheme', {id:id},function(resp) {
                 if (resp.warn === 2){
                     $(".scheme-menu").removeClass("scheme-menu-choice")
                     $(e).addClass("scheme-menu-choice")
                     $("[name='attrSchemeForm']").html(resp.html)
                 }else{
                     msg(resp.warn);
                 }
            },'json');
        }
        $("#schemeInput").bigAutocomplete({
            url:root + 'control/adIndex.html?cla=material&fun=schemeInput',
            callback:function(data,e){
                $("[name='schemeName']").val(data.title)
                $("[name='scheme']").val(data.id)
                var materialId = $("[name='id']").val()
                $.post(root+'control/adIndex.html?cla=material&fun=combination',{id:data.id,materialId:materialId},function (res){
                    $("#attr-group").empty().append(res.html);
                },'json')
        }})
</script>
</li>
efo;
        //表单
        $data['button'] = $this->tableShowButton($button);
        $data['html'] = $this->pageEdit([
            "table" => [
                lang('material.edit.info') => [
                    [
                        must . lang('material.edit.typeId') . "：" => $type_name . hidden(array('name' => 'typeId', 'value' => $typeId)) . $materialTypeBtn,
                        must . lang('material.edit.code') . "：" => text(["name" => "code", 'class' => 'text', 'other' => $readonly, "value" => $info['code']]),
                        must . lang('material.edit.name') . "：" => text(["name" => "name", 'class' => 'text', "value" => $info['name']]),
                        lang('material.edit.model') . "：" => text(["name" => "model", 'class' => 'text', "value" => $info['model']]),
                    ],
                    [
                        lang('material.edit.mainBarcode') . "：" => text(["name" => "mainBarcode", 'class' => 'text', "value" => $info['barcode'] ?: self::creatBarCode()]),
                        must . lang('material.edit.unit') . "：" => select(["name" => "unit", 'title' => lang('material.edit.unit'), 'option' => explode('，', para('materialUnit')), "value" => $info['unit']]),
                        lang('material.edit.unit_one') . "：" => select(["name" => "unit_one", "class" => "width100", 'title' => lang('material.edit.unit_one'), 'option' => explode('，', para('materialUnit')), "value" => $info['unit_one']]).
                            text(array('name' => 'unit_one_num', 'class' => 'width100', 'title' => '辅单位一换算', 'other' => self::digitalFiltering('numPrecision'), 'value' => self::lostZero($info['unit_one_num'], 'numPrecision'))).$tipUnit,
                        lang('material.edit.unit_two') . "：" => select(["name" => "unit_two", "class" => "width100", 'title' => lang('material.edit.unit_two'), 'option' => explode('，', para('materialUnit')), "value" => $info['unit_two']]).
                            text(array('name' => 'unit_two_num', 'class' => 'width100', 'title' => '辅单位二换算', 'other' => self::digitalFiltering('numPrecision'), 'value' => self::lostZero($info['unit_one_num'], 'numPrecision'))).$tipUnit,
                    ],
                    [
                        lang('material.edit.weight') . '：' => text(array('name' => 'new_weight', 'type' => 'number', 'unit' => 'kg', 'value' => $info['new_weight'])),
                        lang('material.edit.text') . "：" => textarea(["name" => "text", 'class' => 'textarea', "value" => $info['text']]),
                    ],
                    [
                        lang('material.edit.img') . "：" => fileUploadClass::addImgComponent($id, '物料档案', self::page, self::page . 'EditForm')
                    ],
                ],
                lang('material.edit.control') => [
                    [
                        must . lang('material.edit.source') . "：" => radio(array('name' => 'source', 'change' => 'getSupplyControl', 'value' => $this->sourceOption, 'checked' => $info['source'] ?: '采购')),
                        must . lang('material.edit.supplyControl') . "：" => "<div id='supplyControl'>" . $this->checkboxCustomized(array('name' => 'supplyControl', 'value' => $this->supplyControlOption($info['source'] ?: '采购'), 'checked' => $info['supplyControl'] ? explode(',', $info['supplyControl']) : [])) . "</div>",
                    ],
                ],
                '属性' => [
                    [
                        'attrHtml' => $attrHtml
                    ]
                ],
                '销售' => [
                    [
                        must . lang('material.edit.OQC') . "：" => radio(array('name' => 'OQC', 'value' => ['1' => '是', '0' => '否'], 'checked' => $info['id'] ? $info['OQC'] : '0')),
                    ],
                    $salePriceArr,
                ],
                lang('material.edit.purchase') => [
                    [
                        must . lang('material.edit.IQC') . "：" => radio(array('name' => 'IQC', 'value' => ['1' => '是', '0' => '否'], 'checked' => $info['id'] ? $info['IQC'] : '0')),
                        lang('material.edit.procurement') . "：" => text(array('name' => 'procurement', 'type' => 'number', 'unit' => 'h', 'value' => $info['procurement'] ?: '')),
                        lang('material.edit.buyTolerance') . "：" => text(array('name' => 'buyTolerance', 'type' => 'number', 'unit' => '%', 'value' => $info['buyTolerance'] ? $info['buyTolerance'] * 100 : 0)),
                    ],
                    $buyPriceArr,
                ],
                lang('material.edit.inventory') => [
                    $bacth,
                    [
                        lang('material.edit.weight') . '：' => text(array('name' => 'weight', 'type' => 'number', 'unit' => 'kg', 'value' => $info['weight'])),
                        lang('material.edit.upStock') . '：' => radio(array('name' => 'upStock', 'value' => ['-1' => '不限', '1' => "&nbsp;" . text(['name' => 'upStockNum', 'type' => 'number', 'value' => $info['upStock'] != -1 ? self::lostZero($info['upStock'], 'numPrecision') : ''])], 'checked' => ($info['upStock'] != -1 && !empty($info['upStock'])) ? '1' : '-1')),
                        lang('material.edit.downStock') . '：' => radio(array('name' => 'downStock', 'value' => ['-1' => '不限', '1' => "&nbsp;" . text(['name' => 'downStockNum', 'type' => 'number', 'value' => $info['downStock'] != -1 ? self::lostZero($info['downStock'], 'numPrecision') : ''])], 'checked' => ($info['downStock'] != -1 && !empty($info['downStock'])) ? '1' : '-1')),
                    ],
                    $costPriceArr,
                ],
                lang('material.edit.produce') => [
                    [
                        must . lang('material.edit.IPQC') . "：" => radio(array('name' => 'IPQC', 'value' => ['1' => '是', '0' => '否'], 'checked' => $info['id'] ? $info['IPQC'] : '0')),
                        lang('material.edit.machiningTolerance') . "：" => text(array('name' => 'machiningTolerance', 'type' => 'number', 'unit' => '%', 'value' => $info['machiningTolerance'] ? $info['machiningTolerance'] * 100 : 0)),
                        lang('material.edit.production') . '：' => text(array('name' => 'production', 'type' => 'number', 'unit' => 'h', 'value' => $info['production'] ?: '')),
                    ],
                ],
                lang('material.edit.outsource') => [
                    [
                        must . lang('material.edit.OIQC') . "：" => radio(array('name' => 'OIQC', 'value' => ['1' => '是', '0' => '否'], 'checked' => $info['id'] ? $info['OIQC'] : '0')),
                        lang('material.edit.outTolerance') . "：" => text(array('name' => 'outTolerance', 'type' => 'number', 'unit' => '%', 'value' => $info['outTolerance'] ? $info['outTolerance'] * 100 : 0)),
                        lang('material.edit.outPeriod') . "：" => text(array('name' => 'outPeriod', 'type' => 'number', 'unit' => 'h', 'value' => $info['outPeriod'] ?: '')),
                    ],
                ],
                lang('material.edit.finance') => [
                    [
                        must . lang('material.edit.subject') . '：' => select(array('name' => 'subject', 'title' => lang('material.edit.choice'), 'option' => $this->checkOption, 'value' => $info['subject'] ?: '产成品')),
                        must . lang('material.edit.costType') . '：' => radio(array('name' => 'costType', 'value' => ['移动加权平均'], 'checked' => $info['costType'] ?: '移动加权平均')),
                    ]
                ]
            ],
            'hidden' => hidden(['name' => 'id', 'value' => $info['id'] ?: $this->get('id')]),
        ]);
        $data['html']   .= <<<efo
<script>
//切换分类
function chooseMaterialType(e){    
    let id = $(e).data('id');
    let materialId = $("[name='id']").val();
    if (id){
         $.post(root+'control/adIndex.html?cla=material&fun=changeMaterialType',{id:id,materialId:materialId},function(res) {
             if (res.warn ==2){
                 location.reload();
             }else{
                 msg(res.warn,'error')
             }
         },'json')
    }
}
//切换来源
function getSupplyControl(e){
     $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=getSupplyControl',{source:e.value},function(res) {
        $('#supplyControl').html(res.html)
     },'json')
}
             //选择仓位
function addTarget(){
    $.post(root+'control/adIndex.html?cla=moveStock&fun=addTargetEdit', $("form[name='locationForm']").serialize(),function(resp) {
         if (resp.warn === 2){
            $('#locationCode').val(resp.text)
            $("[name='positionId']").val(resp.id)
         }else{
             msg(resp.warn);
         }
    },'json');
}
</script>
efo;
        //返回
        return $this->tab($data);
    }

    /**
     * 属性组合
     */
    public function combination(): bool|string
    {
        $id                   = $this->post('id');
        $material_attr_scheme = query("material_attr_scheme", " id = '$id' ");
        $content              = json_decode($material_attr_scheme['content'], true);
        $materialId           = $this->post('materialId');
        $tip                  = self::tipComponent(lang('material.edit.unitTip'));
        $tr[]                 = [lang('material.edit.attr'), lang('material.edit.unitOne') . $tip, lang('material.edit.unitTwo') . $tip, lang('material.edit.barcode'), lang('material.edit.operate')];
        $attr_mx              = is_array($content) ? $content : [];//属性明细
        $json['html']         = '';
        if (is_array($attr_mx)) {
            $result = self::combinations(array_values($attr_mx));
            if (count($result) == count($result, 1)) {
                //一维数组变为二维数组
                foreach ($result as $index => $array) {
                    $result[$index] = [$array];
                }
            }
            foreach ($result as $array) {
                $attr_name = '';//名称
                $hidden    = '';

                $attrMxId = [];
                foreach ($array as $index => $val) {
                    $attrMxId[] = $val;
                }
                asort($attrMxId);
                $material_sku = query(self::table . '_sku', "attr_mx_id = '" . implode(',', $attrMxId) . "' and materialId = '$materialId'");
                $id           = $material_sku['id'] ?: self::getId();//组合ID
                foreach ($array as $index => $val) {
                    $attr_mx = query(self::table . '_attr_detail', " id = '$val'");
                    if ($index > 0) {
                        $attr_name .= '，';
                    }
                    $attr_name .= $attr_mx['value'];
                    $hidden    .= hidden(array('name' => "combinationMxId[{$id}][]", 'value' => $val));
                }

                $tr[] = [
                    $attr_name . hidden(array('name' => 'combinationId[]', 'value' => $id)) . hidden(array('name' => 'attr_name[]', 'value' => $attr_name)) . $hidden,
                    text(array('name' => 'help_unit_one[]', 'other' => self::digitalFiltering('numPrecision'), 'value' => $material_sku['unitOne'] ? self::lostZero($material_sku['unitOne'], 'numPrecision') : 1)),
                    text(array('name' => 'help_unit_two[]', 'other' => self::digitalFiltering('numPrecision'), 'value' => $material_sku['unitTwo'] ? self::lostZero($material_sku['unitTwo'], 'numPrecision') : 1)),
                    text(array('name' => 'barcode[]', 'value' => $material_sku['barcode'] ?: self::creatBarCode())),
                    "<span onclick='decline(this)' class='del-row-button'>" . lang('material.edit.del') . "</span>"
                ];
            }
            $json['html'] = $this->tableMany(['tr' => $tr]);
        }

        return json_encode($json, 320);
    }


    public function getAttr(): bool|string
    {
        //属性
        $name_li = "<li>" . lang('material.attrScheme.type') . "：</li>";
        $mx_Html = "";
        $result  = find(array('table' => 'material_attr', 'where' => " coid = '" . self::$coid . "' order by time asc"));
        foreach ($result['array'] as $array) {
            $name_li .= <<<eof
<li><label class="radioLabel"><input type="checkbox" value="{$array['id']}" name="attr[]" onchange="setAllCheck(this)">&nbsp;{$array['name']}</label></li>
eof;

            $mxResult = find(array('table' => 'material_attr_detail', 'where' => " orderId = '$array[id]' order by list asc"));
            $mx_Html  .= "<ul><li>{$array['name']}：</li>";
            foreach ($mxResult['array'] as $val) {
                $mx_Html .= <<<eof
<li><label class="radioLabel"><input type="checkbox" value="{$val['id']}" name="attr_mx[{$array['id']}][]">&nbsp;{$val['value']}</label></li>
eof;
            }
            $mx_Html .= "</ul>";
        }
        $name_li      .= "<span class='spanButton' style='margin-top: 5px' onclick=\"layer('{$this->get('cla')}','addAttr',{id:''})\">" . lang('material.attrScheme.add') . "</span>";
        $json['type'] = $name_li;
        $json['html'] = $mx_Html;
        return json_encode($json, 320);
    }

    /**
     * 显示输入框
     */
    public function showInput(): bool|string
    {
        $id           = $this->post('id');
        $json['html'] = <<<efo
<li><input name="attr_mx[{$id}][]" type="text" onblur="showAddButton(this)" value=""></li>
efo;
        return json_encode($json, 320);
    }

    /**
     * 显示添加按钮
     * @return bool|string
     */
    public function showAddButton(): bool|string
    {
        $id           = $this->post('id');
        $val          = $this->post('val');//值
        $json['html'] = '';
        if (!empty($val) && !empty($id)) {
            $mxId         = self::getId();
            $json['html'] = <<<efo
<li><span class='background-color-gray li-ico'>{$val}<input name='attr_mx[{$id}][$mxId][id]' type='hidden' value='{$mxId}'><input name='attr_mx[{$id}][$mxId][val]' type='hidden' value='{$val}'></span><a onclick='del_this(this)'><div><span class='u-icon-delete'><i></i></span></div></a></li>
efo;
        }
        return json_encode($json, 320);
    }

    /**
     * 添加一行
     */
    public function addRow(): bool|string
    {
        $id           = self::getId();
        $hidden       = hidden(array('name' => 'attrId[]', 'value' => $id));
        $json['html'] = "
        <tr>
     <td>" . $hidden . text(array('name' => 'attrName[]')) . "</td>
     <td><ul><li><div class='add-attr-button' onclick=\"showInput(this)\">+</div></li></ul></td>
     <td><span class='del-row-button' onclick='decline(this)'>" . lang('material.edit.del') . "</span></td>
</tr>
        ";
        return json_encode($json, 320);
    }

    /**
     * 属性方案保存修改
     */
    public function schemeEdit(): bool|string
    {
        $scheme_id    = $this->post('scheme_id') ?: self::getId();
        $scheme_name  = $this->post('scheme_name');//方案名称
        $attr_mx      = $this->post('attr_mx');//属性明细
        $where        = " coid = '" . self::$coid . "' AND id = '$scheme_id' ";
        $field        = [
            'name'    => $scheme_name,
            'content' => json_encode($attr_mx, 320),
        ];
        $json['html'] = '';
        if (empty($scheme_name)) {
            $json['warn'] = lang('material.schemeEdit.name');
        } elseif (!is_array($attr_mx)) {
            $json['warn'] = lang('material.schemeEdit.combination');
        } else {
            $material_attr_scheme = query("material_attr_scheme", $where);
            if (empty($material_attr_scheme['id'])) {
                $field        = array_merge($field, [
                    'id'   => $scheme_id,
                    'coid' => self::$coid,
                    'stid' => $this->control['stid'],
                ]);
                $json['warn'] = static::insert(["table" => 'material_attr_scheme', "field" => $field,]);
            } else {
                $json['warn'] = static::update([
                    "table" => 'material_attr_scheme',
                    "field" => $field,
                    "where" => $where,
                ]);
            }
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                if ($json['warn'] == '新增成功') {
                    $json['html'] = "<li onclick='switchingScheme(this)' class='scheme-menu scheme-menu-choice' data-id='$scheme_id'>$scheme_name</li>";
                }
                $json['warn'] = 2;
                $json['id']   = $scheme_id;
                $json['name'] = $scheme_name;
            }
        }

        return json_encode($json, 320);
    }

    /**
     * 属性方案保存删除
     */
    public function delScheme(): bool|string
    {
        $scheme_id            = $this->post('scheme_id');
        $where                = " coid = '" . self::$coid . "' AND id = '$scheme_id' ";
        $material_attr_scheme = query("material_attr_scheme", $where);
        if (empty($scheme_id) || empty($material_attr_scheme['id'])) {
            $json['warn'] = lang('material.delScheme.del');
        } else {
            delete(array("table" => 'material_attr_scheme', "where" => " id = '$scheme_id' "));
            $json['warn'] = 2;
            $json['id']   = $scheme_id;
        }

        return json_encode($json, 320);
    }

    /**
     * 切换方案
     */
    public function switchingScheme(): bool|string
    {
        $id                   = $this->post('id') ?: self::getId();
        $material_attr_scheme = query("material_attr_scheme", " id = '$id' ");
        $content              = (array)json_decode($material_attr_scheme['content'], true);
        //属性
        $name_li = $mx_Html = '';
        $result  = find(array('table' => 'material_attr', 'where' => " coid = '" . self::$coid . "' order by time asc"));
        foreach ($result['array'] as $array) {
            $name_li  .= <<<eof
<li><label class="radioLabel"><input type="checkbox" value="{$array['id']}" name="attr[]" onchange="setAllCheck(this)">&nbsp;{$array['name']}</label></li>
eof;
            $values   = isset($content[$array['id']]) ? $content[$array['id']] : [];
            $mxResult = find(array('table' => 'material_attr_detail', 'where' => " orderId = '$array[id]' order by list asc"));
            $mx_Html  .= "<ul><li>{$array['name']}：</li>";
            foreach ($mxResult['array'] as $val) {
                $checked = in_array($val['id'], $values) ? 'checked' : '';
                $mx_Html .= <<<eof
<li><label class="radioLabel"><input type="checkbox" $checked value="{$val['id']}" name="attr_mx[{$array['id']}][]">&nbsp;{$val['value']}</label></li>
eof;
            }
            $mx_Html .= "</ul>";
        }
        $name_li .= "<span class='spanButton' style='margin-top: 5px' onclick=\"layer('{$this->get('cla')}','addAttr',{id:''})\">" . lang('material.switchingScheme.add') . "</span>";
        //表单
        $json['warn'] = 2;
        $json['html'] = "<div class='attr-content'>
                                <p class='scheme-name'><span>" . must . lang('material.switchingScheme.name') . "：</span><span>" . text(array('name' => 'scheme_name', 'class' => "text", 'other' => $material_attr_scheme['name'] == '默认方案' ? 'readonly' : '', 'value' => $material_attr_scheme['name'])) . "</span></p>
                                <ul class='attr-type'>
                                 <li>" . lang('material.switchingScheme.type') . "：</li>
                                     {$name_li}
                                </ul>
                                <div id='attr-catalog'>
                                    {$mx_Html}
                                </div>
                        </div>
                <input name='scheme_id' type='hidden' value='$id'>";
        //返回
        return json_encode($json, 320);
    }

    /**
     * 查询方案名称
     */
    public function serchScheme(): bool|string
    {
        $keyword = $this->post('keyword');
        $where   = $keyword ? " and name like '%$keyword%' " : "";
        //数据查询
        $li     = "<li onclick='switchingScheme(this)' class='scheme-menu scheme-menu-choice' data-id=''>" . lang('material.serchScheme.new') . "</li>";
        $result = find(array('table' => 'material_attr_scheme', 'where' => " coid = '" . self::$coid . "' {$where} order by list asc"));
        foreach ($result['array'] as $array) {
            $li .= "<li onclick='switchingScheme(this)' class='scheme-menu' data-id='$array[id]'>$array[name]</li>";
        }
        $json['html'] = $li;
        return json_encode($json, 320);
    }

    /**
     * 管理属性方案
     */
    public function attrScheme(): bool|string
    {
        //数据查询
        $li     = "<li onclick='switchingScheme(this)' class='scheme-menu scheme-menu-choice' data-id=''>" . lang('material.serchScheme.new') . "</li>";
        $result = find(array('table' => 'material_attr_scheme', 'where' => " coid = '" . self::$coid . "' order by list asc"));
        foreach ($result['array'] as $array) {
            $li .= "<li onclick='switchingScheme(this)' class='scheme-menu' data-id='$array[id]'>$array[name]</li>";
        }
        $searchText = "
			<div id='searchDiv' class='animated fadeInRight' ><input id='searchMenuInput' type='text' autocomplete='off' placeholder='" . lang('material.attrScheme.search') . "'><i onclick='serchScheme(this)' class='container-left-search-ico' style='top: 10px;right: 10px;margin: 0'></i></div>";
        //属性
        $name_li = $mx_Html = '';
        $result  = find(array('table' => 'material_attr', 'where' => " coid = '" . self::$coid . "' order by time asc"));
        foreach ($result['array'] as $array) {
            $name_li .= <<<eof
<li><label class="radioLabel"><input type="checkbox" value="{$array['id']}" name="attr[]" onchange="setAllCheck(this)">&nbsp;{$array['name']}</label></li>
eof;

            $mxResult = find(array('table' => 'material_attr_detail', 'where' => " orderId = '$array[id]' order by list asc"));
            $mx_Html  .= "<ul><li>{$array['name']}：</li>";
            foreach ($mxResult['array'] as $val) {
                $checked = '';
                $mx_Html .= <<<eof
<li><label class="radioLabel"><input type="checkbox" $checked value="{$val['id']}" name="attr_mx[{$array['id']}][]">&nbsp;{$val['value']}</label></li>
eof;
            }
            $mx_Html .= "</ul>";
        }
        $name_li .= "<span class='spanButton' style='margin-top: 5px' onclick=\"layer('{$this->get('cla')}','addAttr',{id:''})\">" . lang('material.attrScheme.add') . "</span>";
        //表单
        $html = "<div id='scheme-name'>
                    $searchText
                    <div>
                        <ul id='navigationDiv'>$li</ul>
                    </div>
                </div>
                <div class='attr-block'>
                        <p>
                            <span class='spanButton' onclick=\"delScheme();\">" . lang('material.attrScheme.del') . "</span>
                            <span class='spanButton li-btn-blue-bg' onclick='schemeEdit()'>" . lang('material.attrScheme.save') . "</span>
                        </p>
                        <form name='attrSchemeForm'>
                        <div class='attr-content'>
                                <p class='scheme-name'><span>" . must . "" . lang('material.attrScheme.manage') . "：</span><span>" . text(array('name' => 'scheme_name', 'class' => "text", 'value' => "")) . "</span></p>
                                <ul class='attr-type'>
                                 <li>" . lang('material.attrScheme.type') . "：</li>
                                     {$name_li}
                                </ul>
                                <div id='attr-catalog'>
                                    {$mx_Html}
                                </div>
                        </div>
                        <input name='scheme_id' type='hidden' value=''>
                    </form>
                </div>
                <style>
                    #scheme-name{
                        padding: 10px;
                        width: 20%;
                        float: left;
                        border-right: 1px solid #ccc;
                        height: 100%;
                    }
                    .attr-block{
                        width: 70%;
                        text-align: center;
                        float: left;
                        margin-left: 20px;
                    }
                    #searchMenuInput {
                        border: 1px solid #ddd!important;
                        width: 145px!important;
                    }
                    #searchDiv{
                        margin-bottom: 1px;
                    }
                    .scheme-menu{
                        width: 185px;
                        padding: 10px 5px;
                        cursor: pointer;
                    }
                    .scheme-menu-choice{
                        background-color: #9ed0ff;
                    }
                    .scheme-name{
                        margin: 20px 5px;
                    }
                    .attr-type{
                        background-color: #ffffff!important;
                    }
                    #attr-catalog{
                        background-color: #F2F2F2;
                        margin: 10px 0 0 10px;
                    }
                </style>";
        //返回
        return $this->layer(["title" => lang('material.attrScheme.manageAttr'), "height" => 600, 'width' => 1000, "html" => $html, 'button'=>' ']);
    }

    /**
     * 管理属性方案编辑
     */
    public function attrSchemeEdit(): bool|string
    {
        $attr_id    = $this->post('attrId') ?: [];//属性ID
        $attr_mx_id = $this->post('attr_mx') ?: [];//属性明细ID;
        $attrName   = $this->post('attrName') ?: [];//属性值
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = lang('material.attrSchemeEdit.power');
        } elseif (!empty($attr_id) && !is_array($attr_id)) {
            $json['warn'] = lang('material.attrSchemeEdit.attrId');
        } elseif (!empty($attrName) && !is_array($attrName)) {
            $json['warn'] = lang('material.attrSchemeEdit.attrValue');
        } elseif (!empty($attr_mx_id) && !is_array($attr_mx_id)) {
            $json['warn'] = lang('material.attrSchemeEdit.attMx');
        } elseif (count($attr_id) != count(array_filter($attrName))) {
            $json['warn'] = lang('material.attrSchemeEdit.empty');
        } else {
            $mx_id_list = [];
            foreach ($attr_id as $index => $id) {
                $attr  = query(self::table . '_attr', "id = '$id'");
                $field = [
                    'name'       => $attrName[$index],
                    "updateTime" => $this->time,
                ];
                if (empty($attr['id'])) {
                    //新增属性
                    $field = array_merge($field, ["id" => $id, 'coid' => self::$coid, 'stid' => self::$stid, "time" => $this->time]);
                    insert(["table" => self::table . '_attr', "field" => $field]);
                } else {
                    //更新属性
                    update(["table" => self::table . '_attr', "field" => $field, "where" => "id = '" . $id . "'"]);
                }
                //属性明细
                $attr_mx = $attr_mx_id[$id];
                if (is_array($attr_mx)) {
                    foreach ($attr_mx as $mx) {
                        $attr_mx = query(self::table . '_attr_detail', "id = '$mx[id]'");
                        $field   = [
                            'value' => $mx['val'],
                        ];
                        if (empty($attr_mx['id'])) {
                            //新增属性
                            $field = array_merge($field, ["id" => $mx['id'], 'coid' => self::$coid, 'orderId' => $id, "time" => $this->time]);
                            insert(["table" => self::table . '_attr_detail', "field" => $field]);
                        } else {
                            //更新属性
                            update(["table" => self::table . '_attr_detail', "field" => $field, "where" => "id = '" . $mx['id'] . "'"]);
                        }
                        $mx_id_list[] = $mx['id'];
                    }
                }
            }

            //删除属性
            delete(array('table' => self::table . '_attr', 'where' => " id not in ('" . implode("','", $attr_id) . "') and coid = '" . self::$coid . "' and name !='" . self::defaultName . "'"));
            //删除属性明细
            delete(array('table' => self::table . '_attr_detail', 'where' => " coid = '" . self::$coid . "' and orderId not in ('" . implode("','", $attr_id) . "') and id not in (select distinct attrMxId from material_sku_detail where coid = '" . self::$coid . "') and orderId NOT IN (select id from material_attr where coid = '" . self::$coid . "' and name ='" . self::defaultName . "')"));
            delete(array('table' => self::table . '_attr_detail', 'where' => " coid = '" . self::$coid . "' and id not in ('" . implode("','", $mx_id_list) . "') and orderId NOT IN (select id from material_attr where coid = '" . self::$coid . "' and name ='" . self::defaultName . "')"));
        }
        $text = str_replace(['{{staffName}}'], [$this->control['name']], lang('material.attrSchemeEdit.log'));
        $this->logText(array("type" => self::page, "text" => $text));
        //提示
        $json['warn'] = 2;
        //返回
        return json_encode($json, 320);
    }

    /**
     * 添加属性界面
     */
    public function addAttr(): bool|string
    {
        //数据查询
        $tr[]   = [lang('material.addAttr.type'), lang('material.addAttr.value'), "<span class='del-row-button' onclick=\"addRow()\">" . lang('material.addAttr.add') . "</span>"];
        $result = find(array('table' => 'material_attr', 'where' => " coid = '" . self::$coid . "' order by time"));
        foreach ($result['array'] as $array) {
            $mxResult = find(array('table' => 'material_attr_detail', 'where' => " orderId ='$array[id]' order by list asc"));
            $mxName   = "<ul class='addAttr'>";
            foreach ($mxResult['array'] as $val) {
                $del_ico = "<a onclick='del_this(this)' href='javascript:void(0)'><div><span class='u-icon-delete'><i></i></span></div></a>";
                if ($array['name'] == self::defaultName) {
                    $del_ico = '';
                }
                $mxName .= "<li><span class='background-color-gray li-ico'>{$val['value']}<input name='attr_mx[{$array['id']}][{$val['id']}][id]' type='hidden' value='{$val['id']}'><input name='attr_mx[{$array['id']}][{$val['id']}][val]' type='hidden' value='{$val['value']}'></span>{$del_ico}</li>";
            }
            $hidden = hidden(array('name' => 'attrId[]', 'value' => $array['id']));
            $del    = "<span class='del-row-button' onclick='decline(this)'>" . lang('material.addAttr.del') . "</span>";
            $name   = text(array('name' => 'attrName[]', 'class' => 'select', 'value' => $array['name']));
            if ($array['name'] == self::defaultName) {
                //默认属性不可编辑
                $del    = '';
                $hidden = '';
                $name   = $array['name'];
            } else {
                $mxName .= "<li><div class='add-attr-button' onclick=\"showInput(this)\">+</div></li></ul>";
            }
            $tr[] = [$hidden . $name, $mxName, $del];
        }
        //表单
        $html = "<div id='attr-table' style='padding: 10px'><form name='attrForm'>" . $this->tableMany(['tr' => $tr, 'end' => true]) . "</form></div><div style='width: 100%;text-align: center'><span class='spanButton li-btn-blue-bg' onclick='commitData()'>" . lang('material.addAttr.sure') . "</span><span class='spanButton' onclick=\" $('#materialAddAttr').hide();\">" . lang('material.addAttr.cancel') . "</span></div>";
        //返回
        return $this->layer(["title" => lang('material.addAttr.manage'), "height" => 600, 'width' => 1000, "html" => $html, 'button'=>' ']);
    }

    /**
     * 属性编辑
     */
    public function addAttrEdit(): bool|string
    {
        $attr_id    = $this->post('attrId') ?: [];//属性ID
        $attr_mx_id = $this->post('attr_mx') ?: [];//属性明细ID;
        $attrName   = $this->post('attrName') ?: [];//属性值
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = lang('material.attrSchemeEdit.power');
        } elseif (!empty($attr_id) && !is_array($attr_id)) {
            $json['warn'] = lang('material.attrSchemeEdit.attrId');
        } elseif (!empty($attrName) && !is_array($attrName)) {
            $json['warn'] = lang('material.attrSchemeEdit.attrValue');
        } elseif (!empty($attr_mx_id) && !is_array($attr_mx_id)) {
            $json['warn'] = lang('material.attrSchemeEdit.attMx');
        } elseif (count($attr_id) != count(array_filter($attrName))) {
            $json['warn'] = lang('material.attrSchemeEdit.empty');
        } else {
            $mx_id_list = [];
            foreach ($attr_id as $index => $id) {
                $attr = query(self::table . '_attr', "id = '$id'");
                if ($attr['name'] == self::defaultName || $attrName[$index] == self::defaultName) {
                    continue;
                }
                $field = [
                    'name'       => $attrName[$index],
                    "updateTime" => $this->time,
                ];
                if (empty($attr['id'])) {
                    //新增属性
                    $field = array_merge($field, ["id" => $id, 'coid' => self::$coid, 'stid' => self::$stid, "time" => $this->time]);
                    insert(["table" => self::table . '_attr', "field" => $field]);
                } else {
                    //更新属性
                    update(["table" => self::table . '_attr', "field" => $field, "where" => "id = '" . $id . "'"]);
                }
                //属性明细
                $attr_mx = $attr_mx_id[$id];
                if (is_array($attr_mx)) {
                    foreach ($attr_mx as $mx) {
                        $attr_mx = query(self::table . '_attr_detail', "id = '$mx[id]'");
                        $field   = [
                            'value' => $mx['val'],
                        ];
                        if (empty($attr_mx['id'])) {
                            //新增属性
                            $field = array_merge($field, ["id" => $mx['id'], 'coid' => self::$coid, 'orderId' => $id, "time" => $this->time]);
                            insert(["table" => self::table . '_attr_detail', "field" => $field]);
                        } else {
                            //更新属性
                            update(["table" => self::table . '_attr_detail', "field" => $field, "where" => "id = '" . $mx['id'] . "'"]);
                        }
                        $mx_id_list[] = $mx['id'];
                    }
                }
            }

            //删除属性
            delete(array('table' => self::table . '_attr', 'where' => " id not in ('" . implode("','", $attr_id) . "') and coid = '" . self::$coid . "' and name !='" . self::defaultName . "'"));
            //删除属性明细
            delete(array('table' => self::table . '_attr_detail', 'where' => " coid = '" . self::$coid . "' and orderId not in ('" . implode("','", $attr_id) . "') and id not in (select distinct attrMxId from material_sku_detail where coid = '" . self::$coid . "') and orderId NOT IN (select id from material_attr where coid = '" . self::$coid . "' and name ='" . self::defaultName . "')"));
            delete(array('table' => self::table . '_attr_detail', 'where' => " coid = '" . self::$coid . "' and id not in ('" . implode("','", $mx_id_list) . "') and orderId NOT IN (select id from material_attr where coid = '" . self::$coid . "' and name ='" . self::defaultName . "')"));
        }
        $text = str_replace(['{{staffName}}'], [$this->control['name']], lang('material.attrSchemeEdit.log'));
        $this->logText(array("type" => self::page, "text" => $text));
        //提示
        $json['warn'] = 2;
        //返回
        return json_encode($json, 320);
    }

    /** 默认属性方案
     * @param $id
     * @return array
     */
    public function defaultScheme($id): array
    {
        $material_attr_scheme = query("material_attr_scheme", " id = '$id' ");
        $content              = json_decode($material_attr_scheme['content'], true);
        $tr                   = [];
        $attr_mx              = is_array($content) ? $content : [];//属性明细
        if (is_array($attr_mx)) {
            $result = self::combinations(array_values($attr_mx));
            if (count($result) == count($result, 1)) {
                //一维数组变为二维数组
                foreach ($result as $index => $array) {
                    $result[$index] = [$array];
                }
            }
            foreach ($result as $array) {
                $attr_name = '';//名称
                $hidden    = '';

                $attrMxId = [];
                foreach ($array as $index => $val) {
                    $attrMxId[] = $val;
                }
                asort($attrMxId);
                $id = self::getId();//组合ID
                foreach ($array as $index => $val) {
                    $attr_mx = query(self::table . '_attr_detail', " id = '$val'");
                    if ($index > 0) {
                        $attr_name .= '，';
                    }
                    $attr_name .= $attr_mx['value'];
                    $hidden    .= hidden(array('name' => "combinationMxId[{$id}][]", 'value' => $val));
                }

                $tr[] = [
                    $attr_name . hidden(array('name' => 'combinationId[]', 'value' => $id)) . hidden(array('name' => 'attr_name[]', 'value' => $attr_name)) . $hidden,
                    text(array('name' => 'help_unit_one[]', 'other' => self::digitalFiltering('numPrecision'), 'value' => 1)),
                    text(array('name' => 'help_unit_two[]', 'other' => self::digitalFiltering('numPrecision'), 'value' => 1)),
                    text(array('name' => 'barcode[]', 'value' => self::creatBarCode())),
                    "<span onclick='decline(this)' class='del-row-button'>" . lang('material.edit.del') . "</span>"
                ];
            }
        }
        return $tr;
    }

    /**
     * 属性方案搜索
     *
     * @return false|string
     */
    public function schemeInput(): bool|string
    {
        $key          = $this->post('keyword');//关键词
        $where        = $key ? " and name like '%$key%' " : "";
        $result       = find(array('table' => 'material_attr_scheme', 'field' => 'id,name', 'where' => " coid = '" . self::$coid . "' {$where} order by list asc"));
        $json['warn'] = 2;
        $json['data'] = [];
        foreach ($result['array'] as $val) {
            $json['data'][] = array('title' => $val['name'], 'id' => $val['id']);
        }
        return json_encode($json, 320);
    }

    /**
     * 生成SKU
     * @param $arrays
     * @param int $i
     * @return array
     */
    public static function combinations($arrays, $i = 0): array
    {
        if (!isset($arrays[$i])) {
            return [];
        }
        //取最后一个数组或一维数组时返回
        if ($i == count($arrays) - 1) {
            return $arrays[$i];
        }
        $tmp    = self::combinations($arrays, $i + 1);
        $result = [];
        //
        foreach ($arrays[$i] as $v) {
            foreach ($tmp as $t) {
                $result[] = is_array($t) ? array_merge(array($v), $t) : array($v, $t);
            }
        }
        return $result;
    }
    /**
     * 切换来源
     */
    public function getSupplyControl(): bool|string
    {
        $source = $this->post('source');
        $json['html'] = $this->checkboxCustomized(array('name' => 'supplyControl', 'value' => $this->supplyControlOption($source), 'checked' => []));
        return json_encode($json, 320);
    }

    /** 获取供应控制选择项
     * @param string $source
     * @return array
     */
    public function supplyControlOption(string $source): array
    {
        switch ($source) {
            case '自制':
                $option = [
                    '允许采购' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowPurchase')],
                    '允许销售' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowSale')],
                    '允许库存' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowInventory')],
                    '允许生产' => ['attr' => " onclick='return false' checked ", 'text' => lang('material.supplyControlOption.allowProduce')],
                    '允许委外' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowOutsource')],
                ];
                break;
            case '委外':
                $option = [
                    '允许采购' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowPurchase')],
                    '允许销售' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowSale')],
                    '允许库存' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowInventory')],
                    '允许生产' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowProduce')],
                    '允许委外' => ['attr' => " onclick='return false' checked ", 'text' => lang('material.supplyControlOption.allowOutsource')],
                ];
                break;
            case '虚拟':
                $option = [
                    '允许采购' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowPurchase')],
                    '允许销售' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowSale')],
                    '允许库存' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowInventory')],
                    '允许生产' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowProduce')],
                    '允许委外' => ['attr' => "", 'text' => lang('material.supplyControlOption.allowOutsource')],
                ];
                break;
            default:
                $option = [
                    '允许采购' => ['attr' => " onclick='return false' checked ", 'text' => '允许采购'],
                    '允许销售' => ['attr' => "", 'text' => '允许销售'],
                    '允许库存' => ['attr' => " onclick='return false' checked ", 'text' => '允许库存'],
                    '允许生产' => ['attr' => "", 'text' => '允许生产'],
                    '允许委外' => ['attr' => "", 'text' => '允许委外'],
                ];
                break;
        }
        return $option;
    }


    /*输出多选框
    $data = array(
        "name" => "多选框名称",
        "value" => "数组，键名为多选框的value，键值为多选框的显示结果",
        "checked" => "数组，选中的多选框的value",
    );
    */
    public function checkboxCustomized($data): string
    {
        $html = $checked = '';
        $other = $data['other'] ?? '';
        //如果用此数组中所有的值组成的数组完全等于此数组，则说明此数组为索引数组，反之为关联数组
        if (array_values($data['value']) === $data['value']) {
            foreach ($data['value'] as $key) {
                if (isset($data['checked']) && in_array($key, $data['checked'])) {
                    $checked = "checked";
                } else {
                    $checked = "";
                }
                $html .= "<label class='checkbox'><input name='" . $data['name'] . "[]' type='checkbox' $other value='" . $key . "' " . $checked . "><span></span>&nbsp;" . $key . "</label>&nbsp;&nbsp;";
            }
        } else {
            foreach ($data['value'] as $key => $value) {
                if (isset($data['checked']) && in_array($key, (array)$data['checked'])) {
                    $checked = "checked";
                } else {
                    $checked = "";
                }
                if ($value['attr'] == 'disabled') {
                    $class = 'radioDisabled';
                } else {
                    $class = '';
                }
                $html .= "<label class='checkbox'><input name='" . $data['name'] . "[]' type='checkbox' $other {$value['attr']} value='" . $key . "' " . $checked . "><span class='$class'></span>&nbsp;" . $value['text'] . "</label>&nbsp;&nbsp;";
            }
        }
        //返回
        return $html;
    }

    /**
     * 切换分类
     */
    public function changeMaterialType(): bool|string
    {
        $id = $this->post('id');
        $materialType = query('material_type', "id = '$id'");
        $info = query(self::table, "id = '" . $this->post('materialId') . "'");
        if (empty($materialType['id'])) {
            $json['warn'] = lang('material.changeMaterialType.noType');
        } elseif (empty($info['id'])) {
            $json['warn'] = lang('material.changeMaterialType.noInfo');
        } else {
            $json['warn'] = update(array(
                'table' => self::table,
                "field" => [
                    'typeId' => $id,
                    'typePath' => self::getTypePath($id,'id','/'),
                    'typeName' => self::getTypePath($id)
                ],
                'where' => "id = '$info[id]'"));
            if (in_array($json['warn'], ['新增成功', '更新成功'])) {
                //添加日志
                $text = str_replace(['{{staffName}}', '{{name}}', '{{id}}', '{{materialName}}'], [$this->control['name'], $info['name'], $id, $materialType['name']], lang('material.changeMaterialType.log'));
                $this->logText(array("type" => self::page, "text" => $text));
                $json['warn'] = 2;
                $_SESSION['warn'] = lang('material.changeMaterialType.warn');
            }
        }
        return json_encode($json, 320);
    }

    /**
     * 提示组件
     * @param string $text 提示文字
     * @return string
     */
    public static function tipComponent(string $text): string
    {
        return componentClass::tipComponent($text);
    }

    /**
     * 生成唯一条码
     */
    public static function creatBarCode(): int
    {
        $uid = sprintf('%02d', rand(1000, 9999)) . substr(time(), -2) . substr(microtime(), 2, 4) . sprintf('%02d', rand(1000, 9999));
        while (1) {
            if (static::total(array('table' => 'material', 'where' => "barcode = '$uid'")) == 0) {
                break;
            }
            $uid = sprintf('%02d', rand(1000, 9999)) . substr(time(), -2) . substr(microtime(), 2, 4) . sprintf('%02d', rand(1000, 9999));
        }
        return $uid;
    }

    /*异步处理*/
    public function editEdit(): bool|string
    {
        $fileId = $this->post('imgId') ?? [];
        $id = $this->post('id') ?: self::getId();
        $combinationId   = is_array($this->post('combinationId')) ? $this->post('combinationId') : [];
        $combinationMxId = is_array($this->post('combinationMxId')) ? $this->post('combinationMxId') : [];
        $attrName        = is_array($this->post('attr_name')) ? $this->post('attr_name') : [];
        $help_unit_one   = is_array($this->post('help_unit_one')) ? $this->post('help_unit_one') : [];
        $help_unit_two   = is_array($this->post('help_unit_two')) ? $this->post('help_unit_two') : [];
        $barcode         = is_array($this->post('barcode')) ? $this->post('barcode') : [];
        //赋值
        $field = [
            'typeId' => $this->post('typeId'),
            'typePath' => self::getTypePath($this->post('typeId'),'id','/'),
            'typeName' => self::getTypePath($this->post('typeId')),
            "code" => $this->post('code'),//物料编码
            "name" => $this->post('name'),
            "barcode" => $this->post('mainBarcode'),
            "model" => $this->post('model'),
            "unit" => $this->post('unit'),
            "unit_one" => $this->post('unit_one'),
            "unit_one_num" => $this->post('unit_one_num'),
            "unit_two" => $this->post('unit_two'),
            "unit_two_num" => $this->post('unit_two_num'),
            "text" => $this->post('text'),
            "OQC" => $this->post('OQC'),
            "salePrice" => $this->post('salePrice') ? self::formattingFigure($this->post('salePrice'), 'pricePrecision') : '',
            "downFloat" => (float)$this->post('downFloat') / 100,
            "upFloat" => (float)$this->post('upFloat') / 100,
            "saleRate" => (float)$this->post('saleRate') / 100,
            "source" => $this->post('source'),
            "IQC" => $this->post('IQC'),
            "procurement" => $this->post('procurement'),
            "buyPrice" => $this->post('buyPrice') ? self::formattingFigure($this->post('buyPrice'), 'pricePrecision') : '',
            "downBuy" => (float)$this->post('downBuy') / 100,
            "upBuy" => (float)$this->post('upBuy') / 100,
            "buyRate" => (float)$this->post('buyRate') / 100,
            "isBatch" => $this->post('isBatch'),
            "length" => $this->post('length'),
            "width" => $this->post('width'),
            "height" => $this->post('height'),
            "shelf" => $this->post('shelfDay'),
            "weight" => $this->post('weight'),
            "new_weight" => $this->post('new_weight'),
            "upStock" => $this->post('upStockNum'),
            "downStock" => $this->post('downStockNum'),
            "positionId" => $this->post('positionId'),
            "IPQC" => $this->post('IPQC'),
            "buyTolerance" => (float)$this->post('buyTolerance') / 100,
            "machiningTolerance" => (float)$this->post('machiningTolerance') / 100,
            "OIQC" => $this->post('OIQC'),
            "outTolerance" => (float)$this->post('outTolerance') / 100,
            "outPeriod" => $this->post('outPeriod'),
            "production" => $this->post('production'),
            "subject" => $this->post('subject'),
            "costType" => $this->post('costType'),
            'costPrice' => $this->post('costPrice') ? self::formattingFigure($this->post('costPrice'), 'pricePrecision') : '',
            "supplyControl" => $this->post('supplyControl') ? implode(',', $this->post('supplyControl')) : '',
        ];
        $position = query('warehouse_position', "id = '$field[positionId]'");
        $field['warehouse'] = $position['orderId'] ?? '';
        $field['shelf'] = $this->post('shelf') == -1 ? -1 : $field['shelf'];
        $field['upStock'] = $this->post('upStock') == -1 ? -1 : self::formattingFigure($field['upStock'], 'numPrecision');
        $field['downStock'] = $this->post('downStock') == -1 ? -1 : self::formattingFigure($field['downStock'], 'numPrecision');

        $annotation = [
            'typeId' => lang('material.editEdit.typeId'),
            'code' => lang('material.editEdit.code'),
            'name' => lang('material.editEdit.name'),
            'unit' => lang('material.editEdit.unit'),
            'source' => lang('material.editEdit.source'),
            'supplyControl' => lang('material.editEdit.supplyControl'),
            'OQC' => lang('material.editEdit.OQC'),
            'IQC' => lang('material.editEdit.IQC'),
            'isBatch' => lang('material.editEdit.isBatch'),
            'shelf' => lang('material.editEdit.shelf'),
            'IPQC' => lang('material.editEdit.IPQC'),
            'subject' => lang('material.editEdit.subject'),
            'costType' => lang('material.editEdit.costType'),
        ];
        $rules = [
            'typeId' => 'required',
            'code' => 'required',
            'name' => 'required',
            'unit' => 'required',
            'source' => 'required',
            'supplyControl' => 'required',
            'OQC' => 'required',
            'IQC' => 'required',
            'isBatch' => 'required',
            'shelf' => 'required',
            'IPQC' => 'required',
            'subject' => 'required',
            'costType' => 'required',
        ];
        // 校验是否符合规则
        $vt = new \verify();
        $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
        if ($result === false) {
            $json['warn'] = $vt->getErrs()[0];  // 多个规则提示最前面一条
            goto resp;
        }
        $info = query(self::table, " id = '" . $id . "' ");
        //判断
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = lang('material.editEdit.power');
        } elseif (static::total(array('table' => self::table, 'where' => " and code = '$field[code]' and coid ='" . self::$coid . "' and id !='$id'")) > 0) {
            $json['warn'] = lang('material.editEdit.repeat');
        } elseif (($field['unit_one'] || $field['unit_two']) && ($field['unit_one'] == $field['unit_two'] || $field['unit'] == $field['unit_two'] || $field['unit'] == $field['unit_one'])) {
            $json['warn'] = lang('material.editEdit.noCommon');
        } elseif (empty($info['id'])) {
            $field = array_merge($field, ["id" => $id, 'coid' => self::$coid, 'stid' => self::$stid, 'state' => '启用', "time" => $this->time]);
            $json['warn'] = static::insert(["table" => self::table, "field" => $field], false);
        } else {
            $json['warn'] = static::update(["table" => self::table, "field" => $field, "where" => "id = '" . $this->post('id') . "'"], false);
        }
        if (in_array($json['warn'], array("新增成功", "更新成功"))) {
            //属性
            $idArr = [];
            foreach ($combinationId as $index => $skuId) {
                $attrMxId = [];
                foreach ($combinationMxId[$skuId] as $skuMxId) {
                    $attrMxId[] = $skuMxId;
                }
                asort($attrMxId);
                $attrMxStr    = implode(',', $attrMxId);
                $material_sku = query(self::table . '_sku', "materialId = '$info[id]' and attr_mx_id = '" . $attrMxStr . "'");

                $material_sku_id = $material_sku['id'] ?: $skuId;
                $idArr[]         = $material_sku_id;
                if (empty($material_sku['id'])) {
                    //新增
                    static::insert([
                        'table' => self::table . '_sku',
                        'field' => [
                            'id'         => $material_sku_id,
                            'coid'       => self::$coid,
                            'materialId' => $id,
                            'name'       => $attrName[$index],
                            'unitOne'    => $help_unit_one[$index] ?: 1,
                            'unitTwo'    => $help_unit_two[$index] ?: 1,
                            'barcode'    => $barcode[$index],
                            'attr_mx_id' => $attrMxStr,
                            'updateTime' => $this->time,
                            'time'       => $this->time,
                        ],
                    ]);
                } else {
                    //更新
                    static::update([
                        'table' => self::table . '_sku',
                        'field' => [
                            'name'       => $attrName[$index],
                            'unitOne'    => $help_unit_one[$index] ?: 1,
                            'unitTwo'    => $help_unit_two[$index] ?: 1,
                            'barcode'    => $barcode[$index],
                            'attr_mx_id' => $attrMxStr,
                        ],
                        'where' => " id = '$material_sku_id'",
                    ]);
                }
                //插入属性明细
                foreach ($combinationMxId[$skuId] as $skuMxId) {
                    $skuMx = query(self::table . '_sku_detail', "skuId = '$skuId' and attrMxId = '$skuMxId'");
                    if (empty($skuMx['id'])) {
                        static::insert([
                            'table' => self::table . '_sku_detail',
                            'field' => [
                                'id'         => self::getId(),
                                'coid'       => self::$coid,
                                'materialId' => $id,
                                'skuId'      => $material_sku_id,
                                'attrMxId'   => $skuMxId,
                                'time'       => $this->time,
                            ],
                        ]);
                    }
                }
            }
            //已使用的属性保留，不可删除
            $result = find(array('table' => self::table . '_sku', 'field' => 'id', 'where' => "materialId = '$id' and id not in ('" . implode("','", $idArr) . "')"));
            foreach ((array)$result['array'] as $array) {
                if (static::total(array('table' => 'sale_order_detail', 'where' => "materialSkuId = '$array[id]'")) > 0 || static::total(array('table' => 'purchase_order_detail', 'where' => "materialSkuId = '$array[id]'")) > 0 || static::total(array('table' => 'inventory_record', 'where' => "materialSkuId = '$array[id]'")) > 0) {
                    $idArr[] = $array['id'];
                }
            }
            //删除多余的值
            delete(array('table' => self::table . '_sku', 'where' => "materialId = '$id' and id not in ('" . implode("','", $idArr) . "')"));
            delete(array('table' => self::table . '_sku_detail', 'where' => "materialId = '$id' and skuId not in ('" . implode("','", $idArr) . "')"));
            //更新文件
            update(array('table' => 'file', 'field' => ['targetId' => $id], 'where' => " targetId = '' and id in ('" . implode("','", $fileId) . "')"));
            //添加日志
            $type = mb_substr($json['warn'], 0, 2, 'utf-8');
            $text = str_replace(['{{staffName}}', '{{type}}', '{{name}}', '{{id}}'], [$this->control['name'], $type, $field['name'], $id], lang('material.editEdit.log'));
            $this->logText(array("type" => self::page, "text" => $text));
            //提示
            $_SESSION['warn'] = $json['warn'];
            $json['warn'] = 2;
            if ($this->get('source') == 'home') {
                $json['href'] = root . 'control/adIndex.html?cla=' . self::page . '&fun=edit&typeId=' . $field['typeId'];
            } else {
                $json['href'] = root . 'control/adIndex.html?cla=' . self::page . '&fun=detail&id=' . $id;
            }
        }
        //返回
        resp:
        return json_encode($json, 320);
    }

    /**
     * 明细
     * @return bool|string
     */
    public function detail(): bool|string
    {
        $info = query(self::table, " id = '" . $this->get('id') . "' ");
        if (!$this->power(self::page, "see")) {
            $html = lang('material.detail.power');
        } elseif (empty($info['id'])) {
            $html = lang('material.detail.noFind');
        } else {
            $data = [
                "id" => $info['id'],
                "title" => $info['name'],
                'menu' => [
                    "detail" => lang('material.detail.info'),
                    'attr' => '属性',
                    'bom' => array("name" => lang('material.detail.bom'), "cla" => "bom", "fun" => "bomList"),
                    'quarantine' => array("name" => lang('material.detail.quarantine'), "cla" => "quarantine", "fun" => "quarantineList"),
                    'routing' => array("name" => lang('material.detail.routing'), "cla" => "routing", "fun" => "routingList"),
                    'supplierPrice' => array("name" => lang('material.detail.supplierPrice'), "cla" => "supplierPriceList", "fun" => "supplierPrice"),
                    'clientPrice' => array("name" => lang('material.detail.clientPrice'), "cla" => "clientPriceList", "fun" => "materialClientPrice"),
                    'file'      => ['cla'=>'file', 'fun'=>'materialFile', 'name'=>'附件'],
                ]
            ];
            //按钮
            $button = [];
            if ($this->power(self::page, "edit")) {
                $button[] = [
                    "name" => lang('material.detail.edit'),
                    "type" => "顶部页卡",
                    'title' => lang('material.detail.edit'),
                    "url" => $this->root . 'control/adIndex.html?cla=' . $this->get('cla') . "&fun=edit&typeId={$info['typeId']}&id=" . $info['id'],
                    'style' => 'li-btn-blue-bg',
                ];
                $state = $info['state'] == '停用' ? lang('material.detail.start') : lang('material.detail.stop');
                $button[] = [
                    "name" => $state,
                    "type" => "点击事件",
                    'title' => lang('material.detail.stateSwitch'),
                    "fun" => "layer('" . $this->get('cla') . "','stateSwitch',{id:'" . $info['id'] . "',type:'{$state}'})",
                ];
                $button[] = [
                    "name" => lang('material.detail.del'),
                    "type" => "弹出层",
                    "cla" => $this->get('cla'),
                    "fun" => "delete",
                    "post" => ["id" => $info['id']],
                ];
            }
            $position = query('warehouse_position', "id = '$info[positionId]'");
            $warehouse = query('warehouse', "id = '$info[warehouse]'");
            //生成表单
            $data['button'] = $this->tableShowButton($button);
            $data['html'] = $this->tableShow([
                '基本信息' => [
                    [
                        lang('material.detail.typeId') => $info['typeName'],
                        lang('material.detail.code') => $info['code'],
                        lang('material.detail.name') => $info['name'],
                        lang('material.detail.model') => $info['model'],
                    ],
                    [
                        lang('material.detail.unit') => $info['unit'],
                        lang('material.detail.unit_one') => $info['unit_one'],
                        '辅单位一换算' => $info['unit_one_num'],
                    ],
                    [
                        lang('material.detail.unit_two') => $info['unit_two'],
                        '辅单位二换算' => $info['unit_two_num'],
                        lang('material.detail.state') => $info['state'],
                    ],
                    [
                        lang('material.detail.weight') => $info['new_weight'],
                        lang('material.detail.text') => pre($info['text']),
                    ],

                ],
                lang('material.detail.materialSupply') => [
                    [
                        lang('material.detail.source') => $info['source'],
                        lang('material.detail.supplyControl') => $info['supplyControl'],
                    ]
                ],
                lang('material.detail.img') => [
                    [
                        fileUploadClass::showImg($info['id'], '物料档案')
                    ]
                ],
            ]);
            $saleBlock = $this->power('material','editPrice')?
                [
                    array(
                        lang('material.detail.OQC') => $info['OQC'] ? '是' : '否',
                        str_replace(['{{unit}}'], [static::$unit], lang('material.detail.salePrice')) => self::lostZero($info['salePrice'], 'pricePrecision'),
                        lang('material.detail.downFloat') => ($info['downFloat'] * 100) . '%',
                        lang('material.detail.upFloat') => ($info['upFloat'] * 100) . '%',
                    ),
                    array(
                        lang('material.detail.saleRate') => ($info['saleRate'] * 100) . '%',
                    )
                ]:
                [
                    array(
                        lang('material.detail.OQC') => $info['OQC'] ? '是' : '否',
                        lang('material.detail.downFloat') => ($info['downFloat'] * 100) . '%',
                        lang('material.detail.upFloat') => ($info['upFloat'] * 100) . '%',
                        lang('material.detail.saleRate') => ($info['saleRate'] * 100) . '%',
                    )
                ]
            ;
            $data['html'] .= $this->tableShow([
                lang('material.detail.sale') => $saleBlock,
            ]);
            $purchaseBlock = $this->power('material','editPrice')?
                [
                    array(
                        lang('material.detail.IQC') => $info['IQC'] ? '是' : '否',
                        lang('material.detail.procurement') => $info['procurement'],
                        lang('material.detail.buyTolerance') => ($info['buyTolerance'] * 100) . '%',
                        str_replace(['{{unit}}'], [static::$unit], lang('material.detail.buyPrice')) => self::lostZero($info['buyPrice'], 'pricePrecision'),
                    ),
                    array(
                        lang('material.detail.downFloat') => ($info['downBuy'] * 100) . '%',
                        lang('material.detail.upFloat') => ($info['upBuy'] * 100) . '%',
                        lang('material.detail.saleRate') => ($info['buyRate'] * 100) . '%',
                    )
                ]:
                [
                    array(
                        lang('material.detail.IQC') => $info['IQC'] ? '是' : '否',
                        lang('material.detail.procurement') => $info['procurement'],
                        lang('material.detail.buyTolerance') => ($info['buyTolerance'] * 100) . '%',
                        lang('material.detail.downFloat') => ($info['downBuy'] * 100) . '%',
                    ),
                    array(
                        lang('material.detail.upFloat') => ($info['upBuy'] * 100) . '%',
                        lang('material.detail.saleRate') => ($info['buyRate'] * 100) . '%',
                    )
                ]
            ;
            $data['html'] .= $this->tableShow([
                lang('material.detail.purchase') => $purchaseBlock,
            ]);
            $data['html'] .= $this->tableShow([
                lang('material.detail.inventory') => [
                    array(
                        lang('material.detail.isBatch') => $info['isBatch'] ? '是' : '否',
                        lang('material.detail.shelf') => $info['shelf'] == -1 ? '不限' : $info['shelf'],
                        lang('material.detail.size') => $info['length'] . '*' . $info['width'] . '*' . $info['height'],
                        lang('material.detail.weight') => $info['weight'],
                    ),
                    ($this->power('material','editPrice')?
                        array(
                            lang('material.detail.downStock') => $info['downStock'] == -1 ? '不限' : self::lostZero($info['downStock'], 'numPrecision'),
                            lang('material.detail.upStock') => $info['upStock'] == -1 ? '不限' : self::lostZero($info['upStock'], 'numPrecision'),
                            lang('material.detail.costPrice') => self::lostZero($info['costPrice'], 'pricePrecision'),
                            lang('material.detail.warehouse') => $warehouse['name'] . ' ' . $position['name'],
                        ):
                        array(
                            lang('material.detail.downStock') => $info['downStock'] == -1 ? '不限' : self::lostZero($info['downStock'], 'numPrecision'),
                            lang('material.detail.upStock') => $info['upStock'] == -1 ? '不限' : self::lostZero($info['upStock'], 'numPrecision'),
                            lang('material.detail.warehouse') => $warehouse['name'] . ' ' . $position['name'],
                        )
                    )
                ],
            ]);
            $data['html'] .= $this->tableShow([
                lang('material.detail.produce') => [
                    array(
                        lang('material.detail.IPQC') => $info['IPQC'] ? '是' : '否',
                        lang('material.detail.machiningTolerance') => ($info['machiningTolerance'] * 100) . '%',
                        lang('material.detail.production') => $info['production'],
                    )
                ],
                lang('material.detail.outsource') => [
                    array(
                        lang('material.detail.OIQC') => $info['OIQC'] ? '是' : '否',
                        lang('material.detail.outTolerance') => ($info['outTolerance'] * 100) . '%',
                        lang('material.detail.outPeriod') => $info['outPeriod'],
                    )
                ],
                lang('material.detail.finance') => [
                    array(
                        lang('material.detail.subject') => $info['subject'],
                        lang('material.detail.costType') => $info['costType'],
                        '存货科目' => subjectClass::getShortName($info['subjectId'],'code').subjectClass::getName($info['subjectId']),
                        '销售收入' => subjectClass::getShortName($info['incomeSubjectId'],'code').subjectClass::getName($info['incomeSubjectId']),
                    ),
                    array(
                        '销售成本' => subjectClass::getShortName($info['costSubjectId'],'code').subjectClass::getName($info['costSubjectId']),
                    ),
                ],
                lang('material.detail.sys') => [
                    [
                        lang('material.detail.creater') => self::findStaff($info['stid']),
                        lang('material.detail.update_time') => $info['updateTime'],
                        lang('material.detail.create_time') => $info['time'],
                    ],
                ]
            ]);
            //生成页面
            //生成页面
            $html = $this->tab($data);
        }
        //返回
        return $html;
    }


    /**
     * 物料档案属性
     */
    public function attr(): bool|string
    {
        $html         =
            text(array('name' => 'attrName', 'title' => lang('material.attr.name'))) .
            hidden(array('name' => 'id', 'value' => $this->get('id')));
        $json['html'] = $this->search($html);
        return json_encode($json, 320);
    }

    /**
     * 操作记录
     * @return bool|string
     */
    public function attrSearch(): bool|string
    {
        $id    = $this->post('id');
        $where = " and materialId = '$id'";
        $like  = array(
            'name' => $this->post('attrName')
        );
        $where .= search(array('like' => $like));
        $page  = $this->page([
            "table" => self::table . "_sku",
            "where" => " {$where} ",
            "order" => "`time` desc",
        ]);
        //获取表头
        $tr[] = ['{l.material.attr.attr}', '{l.material.attr.unitOne}', '{l.material.attr.unitTwo}', '{l.material.attr.barcode}', '{l.material.attr.qrCode}'];
        //获取记录
        foreach ($page['array'] as $array) {
            $qrCode = '';
            if (!empty($array['barcode'])) {
                $parameter = urlencode($array['barcode']);
                $qrCode    = "<a target='_blank' href='" . root . "pay/wxpay/wxScanPng.php?url={$parameter}'><img style='width:50px' src='" . root . "pay/wxpay/wxScanPng.php?url={$parameter}'></a>";
            }
            $tr[] = array(
                $array['name'],
                self::lostZero($array['unitOne'], 'numPrecision'),
                self::lostZero($array['unitTwo'], 'numPrecision'),
                $array['barcode'],
                $qrCode
            );
        }
        //控件
        $json['html'] = $page['hint'] . "<form name='topicForm'>" . space . $this->tableMany(array("tr" => $tr)) . "</form>" . $page['button'];
        return json_encode($json, 320);
    }

    /**
     * 销售
     * @return bool|string
     */
    public function sales(): bool|string
    {
        $info = query(self::table, "id = '" . $this->get('id') . "'");
        $field = array(
            array(
                array(
                    lang('material.detail.OQC') => $info['OQC'] ? '是' : '否',
                    str_replace(['{{unit}}'], [static::$unit], lang('material.detail.salePrice')) => self::lostZero($info['salePrice'], 'pricePrecision'),
                ),
                array(
                    lang('material.detail.downFloat') => ($info['downFloat'] * 100) . '%',
                    lang('material.detail.upFloat') => ($info['upFloat'] * 100) . '%',
                    lang('material.detail.saleRate') => ($info['saleRate'] * 100) . '%',
                ),
            ),
        );
        $json['html'] = $this->tableShow($field);
        return json_encode($json, 320);
    }

    /**
     * 采购
     * @return bool|string
     */
    public function procurement(): bool|string
    {
        $info = query(self::table, "id = '" . $this->get('id') . "'");
        $field = array(
            array(
                array(
                    lang('material.detail.IQC') => $info['IQC'] ? '是' : '否',
                    lang('material.detail.procurement') => $info['procurement'],
                    lang('material.detail.buyTolerance') => ($info['buyTolerance'] * 100) . '%',
                ),
                array(
                    str_replace(['{{unit}}'], [static::$unit], lang('material.detail.buyPrice')) => self::lostZero($info['buyPrice'], 'pricePrecision'),
                    lang('material.detail.downFloat') => ($info['downBuy'] * 100) . '%',
                    lang('material.detail.upFloat') => ($info['upBuy'] * 100) . '%',
                ),
                array(
                    lang('material.detail.saleRate') => ($info['buyRate'] * 100) . '%',
                )
            ),
        );
        $json['html'] = $this->tableShow($field);
        return json_encode($json, 320);
    }

    /**
     * 库存
     * @return bool|string
     */
    public function inventory(): bool|string
    {
        $info = query(self::table, "id = '" . $this->get('id') . "'");
        $position = query('warehouse_position', "id = '$info[positionId]'");
        $warehouse = query('warehouse', "id = '$info[warehouse]'");
        $field = array(
            array(
                array(
                    lang('material.detail.isBatch') => $info['isBatch'] ? '是' : '否',
                    lang('material.detail.shelf') => $info['shelf'] == -1 ? '不限' : $info['shelf'],
                    lang('material.detail.size') => $info['length'] . '*' . $info['width'] . '*' . $info['height'],
                ),
                array(
                    lang('material.detail.weight') => $info['weight'],
                    lang('material.detail.downStock') => $info['downStock'] == -1 ? '不限' : self::lostZero($info['downStock'], 'numPrecision'),
                    lang('material.detail.upStock') => $info['upStock'] == -1 ? '不限' : self::lostZero($info['upStock'], 'numPrecision'),
                ),
                array(
                    lang('material.detail.costPrice') => self::lostZero($info['costPrice'], 'pricePrecision'),
                    lang('material.detail.warehouse') => $warehouse['name'] . ' ' . $position['name'],
                )
            ),
        );
        $json['html'] = $this->tableShow($field);
        return json_encode($json, 320);
    }

    /**
     * 生产
     * @return bool|string
     */
    public function production(): bool|string
    {
        $info = query(self::table, "id = '" . $this->get('id') . "'");
        $field = array(
            array(
                array(
                    lang('material.detail.IPQC') => $info['IPQC'] ? '是' : '否',
                    lang('material.detail.machiningTolerance') => ($info['machiningTolerance'] * 100) . '%'
                ),
                array(
                    lang('material.detail.production') => $info['production'],
                )
            ),
        );
        $json['html'] = $this->tableShow($field);
        return json_encode($json, 320);
    }

    public function outsource()
    {
        $info = query(self::table, "id = '" . $this->get('id') . "'");
        $field = array(
            array(
                array(
                    lang('material.detail.OIQC') => $info['OIQC'] ? '是' : '否',
                    lang('material.detail.outTolerance') => ($info['outTolerance'] * 100) . '%'
                ),
                array(
                    lang('material.detail.outPeriod') => $info['outPeriod'],
                )
            ),
        );
        $json['html'] = $this->tableShow($field);
        return json_encode($json, 320);
    }

    /**
     * 财务
     * @return bool|string
     */
    public function finance(): bool|string
    {
        $info = query(self::table, "id = '" . $this->get('id') . "'");
        $field = array(
            array(
                array(
                    lang('material.detail.subject') => $info['subject'],
                    lang('material.detail.costType') => $info['costType'],
                ),
            ),
        );
        $json['html'] = $this->tableShow($field);
        return json_encode($json, 320);
    }

    // 操作中转
    public function operate(): bool|string
    {
        $act = $this->post('act') ?? '';
        $pwd = false; // 需要密码
        $form = $power = $word = '';
        switch ($act) {
            case 'delType':
                $act = 'del';
                $msg = lang('material.operate.delType');
                $title = self::page . 'TypeDelete';
                $function = 'deleteType';
                $form = self::page . 'OperateForm, listForm';
                $power = '';
                break;
            default:
                $act = 'del';
                $msg = lang('material.operate.delMaterial');
                $title = self::page . 'Delete';
                $function = 'delete';
                $form = self::page . 'OperateForm, listForm';
                $power = '';
                break;
        }
        if (!$this->power(self::page, $act)) {
            $_SESSION['warn'] = str_replace(['{{msg}}'], [$msg], lang('material.operate.warn'));
            $json = [
                'warn' => 2,
                'href' => root . 'control/adIndex.html?cla=' . $this->get('cla') . '&fun=home',
            ];
        } else {
            return $this->confirm([
                'title' => $title,
                'function' => $function,
                'form' => $form,
                'power' => $power,
                'pwd' => $pwd,
            ]);
        }

        resp:
        return json_encode($json, 320);
    }

    /**
     * 删除分类
     * @return bool|string
     */
    public function deleteType(): bool|string
    {
        $array = $this->post('id');
        if (!$this->power(self::page, "del")) {
            $json['warn'] = lang('material.deleteType.power');
        } elseif (empty($array)) {
            $json['warn'] = lang('material.deleteType.noChoice');
        } else {
            $text = "";
            $x = 0;
            $array = is_array($array) ? $array : [$array];
            foreach ($array as $id) {
                $info = query(self::table . '_type', " id = '$id' ");
                if (!$this->juageDel($id)) {
                    $warn = lang('material.deleteType.fail');
                } else {
                    //递归删除
                    $this->deleteAll($id);
                    //返回
                    $warn = lang('material.deleteType.success');
                    $x++;
                }
                $text .= str_replace(['{{id}}'], [$info['id']], lang('material.deleteType.text')) . $warn . "。<br>";
            }
            self::getSidebarData(reset: true); //重置左侧分类导航栏
            //添加日志
            $text = str_replace(['{{staffName}}'], [$this->control['name']], lang('material.deleteType.warn')) . "<br>" . $text;
            $this->logText(array("type" => self::page, "text" => $text));
            $_SESSION['warn'] = str_replace(['{{x}}'], [$x], lang('material.deleteType.log'));
            $json['warn'] = 2;
            $json['href'] = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=home";
        }
        return json_encode($json, 320);
    }

    public function deleteAll($id)
    {
        $material_type = query(self::table . '_type', "pid = '$id'");
        if ($material_type['id']) {
            $all = find(array('table' => self::table . '_type', 'where' => "pid = '$id'"));
            foreach ($all['array'] as $array) {
                $this->deleteAll($array['id']);
            }
        }
        delete(array('table' => self::table . '_type', 'where' => "id = '$id'"));
    }

    private function juageDel($id): bool
    {
        $bool = true;
        $material_type = query(self::table . '_type', "pid = '$id'");
        if ($material_type['id']) {
            $bool = $this->juageDel($material_type['id']);
        }
        if (static::total(array('table' => self::table, 'where' => "typeId = '$id'")) > 0) {
            return false;
        }
        return $bool;
    }

    /**
     * 删除
     * @return bool|string
     */
    public function delete(): bool|string
    {
        $array = $this->post('listId') ?? $this->post('id');
        if (!$this->power(self::page, "del")) {
            $json['warn'] = lang('material.delete.power');
        } elseif (empty($array)) {
            $json['warn'] = lang('material.delete.noChoice');
        } else {
            $text = "";
            $x = 0;
            $array = is_array($array) ? $array : [$array];
            foreach ($array as $id) {
                $info = query(self::table, " id = '$id' ");
                if ($info['state'] != '停用') {
                    $warn = lang('material.delete.stop');
                } elseif (static::total(array('table' => 'sale_order_detail', 'where' => "materialId = '$id'")) > 0) {
                    $warn = lang('material.delete.usedSale');
                } elseif (static::total(array('table' => 'purchase_order_detail', 'where' => "materialId = '$id'")) > 0) {
                    $warn = lang('material.delete.usedPurchase');
                } elseif (static::total(array('table' => 'inventory_record', 'where' => "materialId = '$id'")) > 0) {
                    $warn = lang('material.delete.usedinventory');
                } else {
                    $result = find(array('table' => 'file', 'where' => "targetId = '$id'"));
                    foreach ($result['array'] as $file) {
                        fileDelete($file['src']);
                    }
                    //删除附件
                    delete(array("table" => "file", "where" => " targetId = '$id' "));
                    //最后删除基本参数
                    delete(array("table" => self::table, "where" => " id = '$id' "));
                    //返回
                    $warn = lang('material.delete.success');
                    $x++;
                }
                $text .= str_replace(['{{id}}'], [$info['id']], lang('material.delete.text')) . $warn . "。<br>";
            }
            //添加日志
            $text = str_replace(['{{staffName}}'], [$this->control['name']], lang('material.delete.warn')) . "<br>" . $text;
            $this->logText(array("type" => self::page, "text" => $text));
            $_SESSION['warn'] = str_replace(['{{x}}'], [$x], lang('material.delete.log'));
            $json['warn'] = 2;
            $json['href'] = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=home";
        }
        return json_encode($json, 320);
    }


    /**
     * 获取当前分类ID的所有子级分类（包括自己）
     * @param $id
     * @return array
     */
    public static function getAllChildTypeId($id): array
    {
        $typeIdArr = [];
        if (empty($id)) {
            return $typeIdArr;
        } else {
            $typeIdArr[] = $id;
            $material_type = query('material_type', "id = '$id'");
            $child = find(array('table' => 'material_type', 'where' => "pid = '$material_type[id]'"));
            foreach ($child['array'] as $array) {
                $result = self::getAllChildTypeId($array['id']);
                $typeIdArr = array_merge($typeIdArr, $result);
            }
        }
        return array_filter($typeIdArr);
    }

    /**
     * 获取物料名称
     * @param $id
     * @param string $interval
     * @param bool $short
     * @return string
     */
    public static function getName($id, $interval = '-', $short = false): string
    {
        $name = '';
        $material = query(self::table, "id = '$id'");
        if (empty($material['id'])) {
            return $name;
        }
        $name .= $material['code'] ? ($material['code'] . $interval) : '';
        $name .= $material['name'] ? (html_entity_decode($material['name']) . $interval) : '';
        if (!$short) {
            $name .= $material['model'] ? ($material['model'] . $interval) : '';
        }
        return rtrim($name, $interval);
    }

    /**
     * 分类选择器
     * @param string $materialTypeId
     * @param string $name
     * @return string
     */
    public static function typeSelect($materialTypeId = '', $name = '',$title=''): string
    {
        $selectorId = suiji();
        $name = $name ?: 'materialTypeId';
        $title = $title?:lang('material.typeSelect.type');
        $materialType = query('material_type', "id = '$materialTypeId'");
        return "<span id='type-box' style='position: relative' class='full'>" . text(array('name' => 'typeName', 'class' => 'text', 'id' => $selectorId, 'title' => $title, 'other' => 'readonly', 'value' => $materialType['name'])) . "<img id=\"layerBut\" data-name='$name' style='position:absolute;right:10px;top:4px;cursor: pointer;' src='" . root . "img/control/find.svg?v=2'/><input id='layer{$selectorId}' type='hidden' name='$name' value='$materialTypeId'></span>" . <<<eof
eof;

    }

    /**
     * 分类模糊查询
     * @return false|string
     */
    public function getMaterialType()
    {
        $val = $this->post('keyword');//关键词
        $json['data'] = [];
        $where = " and coid='" . self::$coid . "'";
        if ($val) {
            $where .= " and name like '%$val%'";
        }
        $all = find(array('table' => 'material_type', 'where' => "1=1 $where order by list asc limit 50"));
        foreach ($all['array'] as $array) {
            $json['data'][] = array('title' => $array['name'], 'id' => $array['id']);
        }
        $json['warn'] = 2;
        return json_encode($json, 320);
    }

    /**
     * Desc : 组合js方法，参数
     * User : you name
     * Date : 2023-12-28 15:41
     * @param $string
     * @param string $event
     * @return string
     */
    public function combinationJsFun($string, $event = 'click'){
        // 支持的类型
        $keys = ['click', 'dblclick'];
        $attribute = '';
        if(in_array($event,$keys)){
            $temp = explode(',', $string);
            // 统计个数
            $length = count($temp);
            $attribute .= ' on' . $event . '="' . $temp[0] . "(this";
            if ($length > 1) {
                for ($i = 1; $i < $length; $i++) {
                    $temp[$i] = trim(str_replace(['\'', '"'], '', $temp[$i]));
                    $attribute .= ", '$temp[$i]'";
                }
            }
            $attribute .= ')"';
        }
        return $attribute;
    }

    /**
     * @return string
     */
    public function addMx($data): string
    {
        $material_type = (!empty($data['material_type']) ?? '') ? $data['material_type']:
            (str_contains($this->get('cla'), 'sale') ? '产品' : '物料');
        $hidden = isset($data['hidden'])?$data['hidden']:'';
        $hidden .= hidden(array("name"=>"material_type","value"=>$material_type));
        $title = isset($data['title'])?$data['title']:'添加'.$material_type;
        $html   =
            materialClass::typeSelect(name: 'typeId',title: $material_type.'分类') .
            text(["name" => "code", "title" => $material_type."编码"]) .
            text(["name" => "name", "title" => $material_type."名称"]).
            text(["name" => "model", "title" => "规格型号"]).
            $hidden
        ;
        $button = '';
        if(isset($data['continueAdding']) && $data['continueAdding']){
            $button .= "<input ".$data['continueAdding']." type='button' class='button m-l-5' value='" . L('toolCollection.addMx.continueAdding') . "'>";
        }
        if(isset($data['sub']) && $data['sub']){
            $button .= "<input ".$data['sub']." type='button' class='button m-l-5' value='" . L('toolCollection.addMx.sub') . "'>";
        }
        $html = $this->search($html, cla: self::page,fun: 'addMxSearch');
        return $this->layer(["title" => $title, "height" => 600, "width" => 1100, "remove" => 1, "html" => $html, "button" => $button]);
    }

    /**
     *添加物料
     */
    public function addMxSearch()
    {
        $material_type = $this->post('material_type');
        $materialId = $this->post('materialId') ? explode(',', $this->post('materialId')) : [];
        $where      = " 1=1 and coid = '" . self::$coid . "' ";
        $where .= $this->post('attach')?base64_decode($this->post('attach')):'';
        //不允许选择重复物料
        if($this->post('notAllowRepeat')){
            $where .= " and id not in ('" . implode("','", $materialId) . "') ";
        }
        $like  = [
            'name' => $this->post('name'),
            'code'   => $this->post('code'),
            'model'  => $this->post('model'),
            'typePath' => $this->post('typeId'),
            'source' => $this->post('source'),
            'supplyControl' => $this->post('supplyControl'),
        ];
        $equal = [
            'state' => '启用',
        ];
        $where .= search(["like" => $like, "=" => $equal]);
        $page  = $this->page([
            "table"   => "material",
            "field"   => "*",
            "where"   => $where,
            'pageNum' => 50,
            "order"   => "`time` ASC",
        ]);
        $formName = $this->post('formName')?:'mxForm';
        $selectType = $this->post('selectType')?:'checkbox';
        //获取表头
        $checkAll = $this->checkAll($formName, "mxId");
        $tr[]     = [$checkAll, $material_type.'分类', $material_type.'编码', $material_type.'名称', '规格型号'];
        //获取记录
        foreach ($page['array'] as $array) {
            if($selectType == 'checkbox') {
                $dominate = $this->dominate([
                    "box" => ["name" => "mxId", "value" => $array['id']],
                ]);
            }else{
                $dominate = "<input name='mxId' value='$array[id]' type='radio' class='radio-bigger'>";
            }
            $tr[]     = [
                $dominate,
                $array['typeName'],
                $array['code'],
                $array['name'],
                zishu($array['model'],30),
            ];
        }
        $hidden = $this->combinationHidden($this->post);
        $json['html'] = $page['hint'] .
            "<form name='".$formName."'>" .
            $this->tableMany(array("tr" => $tr, "showSort" => true, "page" => $page['para'])) .
            $hidden .
            "</form>" .
            $page['button'];
        return json_encode($json, 320);
    }

    /**
     * Desc : 组合隐藏域
     * User : you name
     * Date : 2023-12-28 15:51
     * @param array $data
     * @return string
     */
    public function combinationHidden(array $data):string
    {
        $html = '';
        foreach ($data as $k=>$v){
            $html .= hidden(['name' => $k, 'value' => $v]);
        }
        return $html;
    }


    /**
     * 导入模板字段初始化
     * @return array[]
     */
    public function importFieldInit($classify=''): array
    {
        return match ($classify) {
            default=>  [
                [
                    'columnName'=>'分类',
                    'aliasName'=>'分类(多级用>隔开)',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'物料编码',
                    'aliasName'=>'物料编码',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'物料名称',
                    'aliasName'=>'物料名称',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'规格型号',
                    'aliasName'=>'规格型号',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'主单位',
                    'aliasName'=>'主单位',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'辅单位1',
                    'aliasName'=>'辅单位1',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'辅单位一换算',
                    'aliasName'=>'辅单位一换算',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'辅单位2',
                    'aliasName'=>'辅单位2',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'辅单位二换算',
                    'aliasName'=>'辅单位二换算',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'备注',
                    'aliasName'=>'备注',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'OQC出货检验',
                    'aliasName'=>'OQC出货检验(是/否)',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'销售基准单价',
                    'aliasName'=>'销售基准单价',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'销售下浮下限',
                    'aliasName'=>'销售下浮下限%',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'销售上浮上限',
                    'aliasName'=>'销售上浮上限%',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'默认销售税率',
                    'aliasName'=>'默认销售税率%',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'来源',
                    'aliasName'=>'来源',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'供应控制',
                    'aliasName'=>'供应控制',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'IQC来料检验',
                    'aliasName'=>'IQC来料检验(是/否)',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'采购入库容差',
                    'aliasName'=>'采购入库容差(±)%',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'采购周期',
                    'aliasName'=>'采购周期(h)',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'采购单价',
                    'aliasName'=>'采购单价%',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'采购下浮下限',
                    'aliasName'=>'采购下浮下限%',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'采购上浮上限',
                    'aliasName'=>'采购上浮上限%',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'默认采购税率',
                    'aliasName'=>'默认采购税率%',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'管理批号',
                    'aliasName'=>'管理批号(是/否)',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'尺寸',
                    'aliasName'=>'尺寸(cm,长*宽*高)',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'保质期限',
                    'aliasName'=>'保质期限(天)',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'重量',
                    'aliasName'=>'重量(kg)',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'库存上限',
                    'aliasName'=>'库存上限',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'库存下限',
                    'aliasName'=>'库存下限',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'默认仓库',
                    'aliasName'=>'默认仓库',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'默认仓位',
                    'aliasName'=>'默认仓位',

                    'isMust'=>false,
                ],
                [
                    'columnName'=>'FQC制终检验',
                    'aliasName'=>'FQC制终检验(是/否)',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'生产入库/转序容差',
                    'aliasName'=>'生产入库/转序容差(±)%',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'生产周期',
                    'aliasName'=>'生产周期(h)',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'OIQC委外检验',
                    'aliasName'=>'OIQC委外检验(是/否)',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'委外入库容差',
                    'aliasName'=>'委外入库容差(±)%',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'委外周期',
                    'aliasName'=>'委外周期',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'存货类型',
                    'aliasName'=>'存货类型(产成品/半成品/原材料)',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'成本计价方式',
                    'aliasName'=>'成本计价方式(移动加权平均/先进先出)',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'成本单价',
                    'aliasName'=>'成本单价',
                    'isMust'=>false,
                ],
            ]
        };
    }

    /**
     * 导出模板字段初始化
     * @return array[]
     */
    public function exportFieldInit($classify=''): array
    {
        return match ($classify) {
            default=>  [
                [
                    'columnName'=>'物料名称',
                    'aliasName'=>'物料名称',
                ],
                [
                    'columnName'=>'分类',
                    'aliasName'=>'分类',
                ],
                [
                    'columnName'=>'物料编码',
                    'aliasName'=>'物料编码',
                ],
                [
                    'columnName'=>'规格型号',
                    'aliasName'=>'规格型号',
                ],
                [
                    'columnName'=>'主单位',
                    'aliasName'=>'主单位',
                ],
                [
                    'columnName'=>'辅单位1',
                    'aliasName'=>'辅单位1',
                ],
                [
                    'columnName'=>'辅单位一换算',
                    'aliasName'=>'辅单位一换算',
                ],
                [
                    'columnName'=>'辅单位2',
                    'aliasName'=>'辅单位2',
                ],
                [
                    'columnName'=>'辅单位二换算',
                    'aliasName'=>'辅单位二换算',
                ],
                [
                    'columnName'=>'条码',
                    'aliasName'=>'条码',
                ],
                [
                    'columnName'=>'备注',
                    'aliasName'=>'备注',
                ],
                [
                    'columnName'=>'OQC(出货检验)',
                    'aliasName'=>'OQC(出货检验)',
                ],
                [
                    'columnName'=>'销售基准单价元',
                    'aliasName'=>'销售基准单价元',
                ],
                [
                    'columnName'=>'销售下浮下限%',
                    'aliasName'=>'销售下浮下限%',
                ],
                [
                    'columnName'=>'销售上浮上限%',
                    'aliasName'=>'销售上浮上限%',
                ],
                [
                    'columnName'=>'默认销售税率%',
                    'aliasName'=>'默认销售税率%',
                ],
                [
                    'columnName'=>'来源',
                    'aliasName'=>'来源',
                ],
                [
                    'columnName'=>'供应控制',
                    'aliasName'=>'供应控制',
                ],
                [
                    'columnName'=>'IQC(来料检验)',
                    'aliasName'=>'IQC(来料检验)',
                ],
                [
                    'columnName'=>'采购入库容差(±)%',
                    'aliasName'=>'采购入库容差(±)%',
                ],
                [
                    'columnName'=>'采购周期(h)',
                    'aliasName'=>'采购周期(h)',
                ],
                [
                    'columnName'=>'采购单价元',
                    'aliasName'=>'采购单价元',
                ],
                [
                    'columnName'=>'采购下浮下限%',
                    'aliasName'=>'采购下浮下限%',
                ],
                [
                    'columnName'=>'采购上浮上限%',
                    'aliasName'=>'采购上浮上限%',
                ],
                [
                    'columnName'=>'默认采购税率%',
                    'aliasName'=>'默认采购税率%',
                ],
                [
                    'columnName'=>'管理批号',
                    'aliasName'=>'管理批号',
                ],
                [
                    'columnName'=>'尺寸',
                    'aliasName'=>'尺寸(cm,长*宽*高)',
                ],
                [
                    'columnName'=>'保质期限',
                    'aliasName'=>'保质期限(天)',
                ],
                [
                    'columnName'=>'重量',
                    'aliasName'=>'重量(kg)',
                ],
                [
                    'columnName'=>'库存上限',
                    'aliasName'=>'库存上限',
                ],
                [
                    'columnName'=>'库存下限',
                    'aliasName'=>'库存下限',
                ],
                [
                    'columnName'=>'默认仓库',
                    'aliasName'=>'默认仓库',
                ],
                [
                    'columnName'=>'默认仓位',
                    'aliasName'=>'默认仓位',
                ],
                [
                    'columnName'=>'FQC(制终检验)',
                    'aliasName'=>'FQC(制终检验)',
                ],
                [
                    'columnName'=>'生产入库/转序容差(±)%',
                    'aliasName'=>'生产入库/转序容差(±)%',
                ],
                [
                    'columnName'=>'生产周期',
                    'aliasName'=>'生产周期(h)',
                ],
                [
                    'columnName'=>'OIQC(委外检验)',
                    'aliasName'=>'OIQC(委外检验)',
                ],
                [
                    'columnName'=>'委外入库容差(±)%',
                    'aliasName'=>'委外入库容差(±)%',
                ],
                [
                    'columnName'=>'委外周期',
                    'aliasName'=>'委外周期',
                ],
                [
                    'columnName'=>'存货类型',
                    'aliasName'=>'存货类型',
                ],
                [
                    'columnName'=>'成本计价方式',
                    'aliasName'=>'成本计价方式',
                ],
                [
                    'columnName'=>'成本单价',
                    'aliasName'=>'成本单价',
                ],
                [
                    'columnName'=>'状态',
                    'aliasName'=>'状态',
                ],
                [
                    'columnName'=>'创建人',
                    'aliasName'=>'创建人',
                ],
                [
                    'columnName'=>'创建时间',
                    'aliasName'=>'创建时间',
                ],
            ]
        };
    }
}
